--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/languageinterworkingfw/servicehandler/src/liwservicehandlerimpl.cpp Mon Mar 30 12:51:20 2009 +0300
@@ -0,0 +1,3033 @@
+/*
+* Copyright (c) 2003-2005 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: Implements API for consumer application to access Language
+* Interworking Framework.
+*
+*/
+
+
+
+
+
+
+#include <eikenv.h>
+#include <bautils.h> // file helpers
+#include <liwservicehandler.rsg>
+#include "liwmenubinding.h"
+#include "liwservicehandler.h"
+#include "liwservicehandlerimpl.h"
+#include "liwmenu.h"
+#include "liwuids.hrh"
+#include "liwcommon.hrh"
+#include "liwmenuslot.hrh"
+#include "liwecommonitor.h"
+#include "liwtlsdata.h"
+#include "data_caging_path_literals.hrh"
+
+#include "LiwXmlHandler.h"
+#include "LiwServiceData.h"
+
+#include <RTSecMgrScriptSession.h>
+
+// CONSTANTS
+// Max number of empty menu resource slots.
+const TInt KMaxMenuResources = 16;
+
+// This value tells how many times consumer can call InitializeMenuPaneL() without
+// closing the Options-menu.
+const TInt KMaxPaneIds = KMaxMenuResources;
+
+// The range reserved for individual menu pane.
+const TInt KIndividualMenuPaneIdRange = 10000;
+
+// The whole range that is reserved to all menu panes. Currently value is 170 000.
+const TInt KMenuPaneCommandRange = (KMaxMenuResources + 1) * KIndividualMenuPaneIdRange;
+
+_LIT(KLiwResourceFile, "liwServiceHandler.rsc");
+_LIT(KLiwZDrive, "z:");
+_LIT8(KDataSeparator, "||");
+_LIT(KPerExtension,".per");
+
+const TInt KMaxMenuTitleSize = 100;
+
+// Command id space reserved for single placeholder.
+const TInt KPlaceholderCmdIdRange = 200;
+
+const TInt KMaxLength=255;
+
+const TReal KDefVersion = 1.0;
+const TReal KUnspVersion = 0.0;
+
+void Cleanup(TAny* aAny);
+void InterestCleanup(TAny* aAny);
+void IntArrayCleanup(TAny* aAny);
+void FilteredCleanup(TAny* aAny);
+void Int32ArrayCleanup(TAny* aAny);
+void InterfaceCleanup(TAny* aAny);
+
+_LIT8(KResolverInterface, "IResolver");
+_LIT8(KResolverDomain, "ServiceManager");
+_LIT8(serviceCmdSeparator, "::");
+
+const TInt KDummySrvCmd=1;
+_LIT(KCapabilityCommDD,"CDD");
+_LIT(KCapabilityPowerMgmt,"PMT");
+_LIT(KCapabilityMultimediaDD,"MDD");
+_LIT(KCapabilityReadDeviceData,"RDD");
+_LIT(KCapabilityWriteDeviceData,"WDD");
+_LIT(KCapabilityDRM,"DRM");
+_LIT(KCapabilityTrustedUI,"TUI");
+_LIT(KCapabilityProtServ,"PSV");
+_LIT(KCapabilityDiskAdmin,"DAD");
+_LIT(KCapabilityNetworkControl,"NWC");
+_LIT(KCapabilityAllFiles,"ALF");
+_LIT(KCapabilitySwEvent,"SWE");
+_LIT(KCapabilityNetworkServices,"NWS");
+_LIT(KCapabilityLocalServices,"LOS");
+_LIT(KCapabilityReadUserData,"RUD");
+_LIT(KCapabilityWriteUserData,"WUD");
+_LIT(KCapabilityLocation,"LOC");
+_LIT(KCapabilitySurroundingsDD,"SDD");
+_LIT(KCapabilityUserEnvironment,"USE");
+
+using namespace LIW;
+//
+// LiwServiceHandler
+//
+
+CLiwServiceHandlerImpl* CLiwServiceHandlerImpl::NewL()
+ {
+ CLiwServiceHandlerImpl* handler = new (ELeave) CLiwServiceHandlerImpl();
+ CleanupStack::PushL( handler );
+ handler->ConstructL();
+ CleanupStack::Pop(handler); // handler
+ return handler;
+ }
+
+
+
+CLiwServiceHandlerImpl::CLiwServiceHandlerImpl()
+ {
+ // Nothing to do here.
+ }
+
+
+
+void CLiwServiceHandlerImpl::ConstructL()
+ {
+ TFileName resFile;
+ TCallBack callBack(SynchronizeCallBack, this);
+ iEcomMonitor = CLiwEcomMonitor::NewL(callBack);
+
+
+ iCoeEnv = CCoeEnv::Static();
+ RFs rFs;
+ TInt err = rFs.Connect();
+
+ TFileName dllName;
+ Dll::FileName(dllName);
+
+ TBuf<2> drive = dllName.Left(2);
+ resFile.Copy(drive);
+ resFile.Append(KDC_RESOURCE_FILES_DIR);
+ resFile.Append(KLiwResourceFile);
+ TBool fileExists( BaflUtils::FileExists(rFs, resFile) );
+ if ( ! fileExists )
+ {
+ resFile.Copy(KLiwZDrive);
+ resFile.Append(KDC_RESOURCE_FILES_DIR);
+ resFile.Append(KLiwResourceFile);
+ }
+ rFs.Close();
+ // A Service Handler instance can be created also when CCoeEnv is not
+ // available (e.g. from server applications). In this case, the methods
+ // needing CCoeEnv/CEikonEnv will leave with KErrNotSupported.
+ if(iCoeEnv)
+ {
+ // This is commented to avoid resource file getting locked affecting the IAD update.
+ // Also, there is no use of resource file since LIW does not support menu related services
+ // iResourceOffset = iCoeEnv->AddResourceFileL(resFile);
+ }
+ // CLiwTlsData has a reference count so each OpenL call
+ // must have a matching Close call (done in destructor).
+ // OpenL is called only here, the TLS data object can be
+ // referenced by calling CLiwTlsData::Instance().
+ CLiwTlsData* data = CLiwTlsData::OpenL();
+ iTlsDataOpened = ETrue;
+
+ // CEikMenuPane informs all menu launch observers
+ // when an options menu is launched.
+ data->AddMenuLaunchObserverL( this );
+ }
+
+
+
+CLiwServiceHandlerImpl::~CLiwServiceHandlerImpl()
+ {
+ if (iResourceOffset && iCoeEnv)
+ {
+ // This is commented to avoid resource file getting locked affecting the IAD update.
+ // Also, there is no use of resource file since LIW does not support menu related services
+ // iCoeEnv->DeleteResourceFile(iResourceOffset);
+ }
+ Reset();
+
+ delete iEcomMonitor;
+
+ if ( iTlsDataOpened )
+ {
+ CLiwTlsData* data = CLiwTlsData::Instance();
+ data->RemoveMenuLaunchObserver( this );
+ CLiwTlsData::Close();
+ }
+ }
+
+
+
+void CLiwServiceHandlerImpl::Reset()
+ {
+ iInterestList.ResetAndDestroy();
+ iMenuBindings.ResetAndDestroy();
+ iBaseBindings.ResetAndDestroy();
+ iProviders.ResetAndDestroy();
+
+ iLastInitialized.Reset();
+
+ iMenuPanes.ResetAndDestroy();
+
+ delete iInParams;
+ iInParams = NULL;
+ delete iOutParams;
+ iOutParams = NULL;
+ }
+
+void CLiwServiceHandlerImpl::AttachServiceManagerPluginsL()
+{
+ CLiwCriteriaItem* crit = CLiwCriteriaItem::NewLC(KDummySrvCmd, KResolverInterface, KResolverDomain);
+ crit->SetServiceClass(TUid::Uid(KLiwClassBase));
+
+ RCriteriaArray a;
+ a.AppendL(crit);
+
+ AttachL(a);
+
+ CleanupStack::Pop(crit); // crit
+ a.ResetAndDestroy();
+}
+
+void CLiwServiceHandlerImpl::ServiceManagerPlugin_ListImplementationsL(RArray<TInt32>& aArray,
+ CLiwCriteriaItem* aItem)
+{
+ CLiwGenericParamList* inps = &(InParamListL());
+ CLiwGenericParamList* outps = &(OutParamListL());
+
+ CLiwCriteriaItem* crit = CLiwCriteriaItem::NewLC(KDummySrvCmd, KResolverInterface, KResolverDomain);
+ crit->SetServiceClass(TUid::Uid(KLiwClassBase));
+
+ ExecuteServiceCmdL(*crit, *inps, *outps);
+ CleanupStack::PopAndDestroy(crit); // crit
+
+ TInt pos = 0;
+ MLiwInterface* ifp;
+ const TLiwGenericParam* p = outps->FindFirst(pos, KResolverInterface, EVariantTypeInterface);
+ if (p) {
+ ifp = p->Value().AsInterface();
+ CleanupStack::PushL(TCleanupItem(InterfaceCleanup, ifp));
+ }
+ else
+ return;
+
+ outps->Reset();
+ inps->Reset();
+
+ _LIT8(KId,"id");
+ _LIT8(KCmd,"cmd");
+ _LIT8(KCmdStr,"cmd_str");
+ _LIT8(KType,"type");
+ _LIT8(KListImpl,"ListImplementations");
+
+ inps->AppendL(TLiwGenericParam(KId, TLiwVariant(aItem->Id())));
+ inps->AppendL(TLiwGenericParam(KCmd, TLiwVariant(aItem->ServiceCmd())));
+ inps->AppendL(TLiwGenericParam(KCmdStr, TLiwVariant(aItem->ServiceCmdStr())));
+ inps->AppendL(TLiwGenericParam(KType, TLiwVariant(aItem->ContentType())));
+ ifp->ExecuteCmdL(KListImpl, *inps, *outps);
+
+ pos = 0;
+ p = outps->FindFirst(pos, EGenericParamError);
+ if (p && (p->Value().AsTInt32() == KErrNone)) {
+ pos = 0;
+ const CLiwList* list;
+ _LIT8(KIdList,"id_list");
+ p = outps->FindFirst(pos, KIdList, EVariantTypeList);
+ if (p) {
+ list = p->Value().AsList();
+ for (TInt i = 0; i < list->Count(); i++) {
+ TLiwVariant v;
+ v.PushL();
+ list->AtL(i, v);
+ aArray.AppendL(v.AsTInt32());
+ CleanupStack::Pop(&v);
+ v.Reset();
+ }
+ }
+ }
+
+ CleanupStack::Pop(ifp); // ifp
+ ifp->Close();
+}
+
+CLiwServiceIfBase* CLiwServiceHandlerImpl::ServiceManagerPlugin_CreateImplementationL(TInt32 aImplUid)
+{
+ CLiwGenericParamList* inps = &(InParamListL());
+ CLiwGenericParamList* outps = &(OutParamListL());
+
+ CLiwCriteriaItem* crit = CLiwCriteriaItem::NewLC(KDummySrvCmd, KResolverInterface, KResolverDomain);
+ crit->SetServiceClass(TUid::Uid(KLiwClassBase));
+
+ ExecuteServiceCmdL(*crit, *inps, *outps);
+ CleanupStack::PopAndDestroy(crit); // crit
+
+ TInt pos = 0;
+ MLiwInterface* ifp = NULL;
+ const TLiwGenericParam* p = outps->FindFirst(pos, KResolverInterface, EVariantTypeInterface);
+ if (p) {
+ ifp = p->Value().AsInterface();
+ CleanupStack::PushL(TCleanupItem(InterfaceCleanup, ifp));
+ }
+ else
+ User::Leave(KErrNotFound);
+
+ outps->Reset();
+ inps->Reset();
+ _LIT8(KUid,"uid");
+ _LIT8(KCreateImpl,"CreateImplementation");
+
+ inps->AppendL(TLiwGenericParam(KUid, TLiwVariant(aImplUid)));
+ ifp->ExecuteCmdL(KCreateImpl, *inps, *outps);
+
+ pos = 0;
+ p = outps->FindFirst(pos, EGenericParamError);
+ User::LeaveIfError(p->Value().AsTInt32());
+
+ pos = 0;
+ CLiwServiceIfBase* iface = NULL;
+ _LIT8(KImplPtr, "impl_ptr");
+ p = outps->FindFirst(pos, KImplPtr, EVariantTypeDesC8);
+ if (p) {
+ TPtrC8 buf = p->Value().AsData();
+ if (buf.Size() == sizeof(iface))
+ Mem::Copy(&iface, buf.Ptr(), buf.Size());
+ else
+ User::Leave(KErrNotFound);
+ }
+ else
+ User::Leave(KErrNotFound);
+
+ CleanupStack::Pop(ifp); // ifp
+ ifp->Close();
+
+ return iface;
+}
+
+void CLiwServiceHandlerImpl::ListProvidersForCriteriaL(RArray<TInt>& aResult,
+ CLiwCriteriaItem& aItem)
+ {
+ TInt i;
+
+ for (i = 0; i < iProviders.Count(); i++)
+ {
+ if (iProviders[i]->HasCriteria(aItem))
+ {
+ User::LeaveIfError(aResult.Append(iProviders[i]->ImplementationUid().iUid));
+ }
+ }
+ }
+
+
+
+TInt CLiwServiceHandlerImpl::NbrOfProviders(const CLiwCriteriaItem* aCriteria)
+ {
+ if(!aCriteria)
+ {
+ return 0;
+ }
+
+ TInt i, j;
+
+ for (i = 0; i < iBaseBindings.Count(); i++)
+ {
+ for (j = 0; j < iBaseBindings[i]->Interest().Count(); j++)
+ {
+ if ((*iBaseBindings[i]->Interest()[j]) == (*aCriteria))
+ {
+ return iBaseBindings[i]->NumberOfProviders();
+ }
+ }
+ }
+
+ for (i = 0; i < iMenuBindings.Count(); i++)
+ {
+ for (j = 0; j < iMenuBindings[i]->Interest().Count(); j++)
+ {
+ if ((*iMenuBindings[i]->Interest()[j]) == (*aCriteria))
+ {
+ return iMenuBindings[i]->NumberOfProviders();
+ }
+ }
+ }
+
+ return 0;
+ }
+
+
+
+void CLiwServiceHandlerImpl::AttachL(TInt aInterestResourceId)
+ {
+ // CCoeEnv/CEikonEnv needs to be accessible.
+ if(!iCoeEnv)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ RCriteriaArray interest, filtered;
+
+ CleanupStack::PushL( TCleanupItem( InterestCleanup, &interest ) );
+ CleanupStack::PushL( TCleanupItem( FilteredCleanup, &filtered ) );
+
+ TResourceReader reader;
+ iCoeEnv->CreateResourceReaderLC(reader, aInterestResourceId);
+ ReadInterestListL(reader, interest);
+ CleanupStack::PopAndDestroy(); //reader
+
+ FilterInterestListL(interest, filtered);
+
+ DoAttachL(filtered,NULL);
+
+ filtered.Reset();
+
+ CleanupStack::Pop(&filtered); // filtered
+ CleanupStack::Pop(&interest); // interest
+ }
+
+
+
+TInt CLiwServiceHandlerImpl::AttachL(const RCriteriaArray& aInterest)
+ {
+ return (this->AttachL(aInterest,NULL));
+ }
+
+TInt CLiwServiceHandlerImpl::AttachL(const RCriteriaArray& aInterest ,CRTSecMgrScriptSession* aSecMgrScriptSession)
+ {
+ RCriteriaArray interest, filtered;
+
+ CleanupStack::PushL( TCleanupItem( InterestCleanup, &interest ) );
+ CleanupStack::PushL( TCleanupItem( FilteredCleanup, &filtered ) );
+
+ for(TInt i = 0; i < aInterest.Count(); i++)
+ {
+ CLiwCriteriaItem* item = CLiwCriteriaItem::NewLC();
+
+ item->SetId( aInterest[i]->Id() );
+ if (aInterest[i]->ServiceCmd() == KLiwCmdAsStr)
+ item->SetServiceCmdL( aInterest[i]->ServiceCmdStr() );
+ else
+ item->SetServiceCmd( aInterest[i]->ServiceCmd() );
+ item->SetContentTypeL( aInterest[i]->ContentType() );
+ item->SetServiceClass( aInterest[i]->ServiceClass() );
+
+ item->SetOptions( aInterest[i]->Options() );
+
+ //Setting the imetadataOptions of item
+ TLiwVariant metadataOption;
+ metadataOption.PushL();
+
+ aInterest[i]->GetMetaDataOptions(metadataOption);
+ item->SetMetaDataOptions(metadataOption);
+ metadataOption.Reset();
+
+ item->SetDefaultProvider( (aInterest[i]->DefaultProvider()).iUid );
+ item->SetMaxProviders( aInterest[i]->MaxProviders() );
+
+ User::LeaveIfError(interest.Append(item));
+ CleanupStack::Pop(&metadataOption);
+ CleanupStack::Pop(item);
+ }
+
+ FilterInterestListL(interest, filtered);
+
+ TInt result = DoAttachL(filtered,aSecMgrScriptSession);
+
+ filtered.Reset();
+
+ CleanupStack::Pop(&filtered); // filtered
+ CleanupStack::Pop(&interest); // interest
+
+ return result;
+ }
+
+TInt CLiwServiceHandlerImpl::DoAttachL(const RCriteriaArray& aInterest,CRTSecMgrScriptSession* aSecMgrScriptSession)
+ {
+ CLiwBinding* bind;
+ TInt success = -1;
+ for (TInt i = 0; i < aInterest.Count(); i++)
+ {
+ bind = CLiwBinding::NewLC();
+
+ success = ResolveProvidersL(bind, aInterest[i],aSecMgrScriptSession);
+
+ if (success == KLiwServiceLoadSuccess)
+ {
+ User::LeaveIfError(iBaseBindings.Append( bind ));
+ CleanupStack::Pop(bind); // bind
+ bind->AddCriteriaL(aInterest[i]);
+
+ // Initialise providers.
+ for (TInt k = 0; k < bind->NumberOfProviders(); k++)
+ {
+ // Trap the initialisation. If not done, a leaving provider
+ // could prevent the initialisation of other providers.
+ TRAPD(err, bind->BaseProvider(k)->InitialiseL(*this, bind->Interest()));
+
+
+
+ if(err)
+ {
+#ifdef _DEBUG
+ RDebug::Print(_L("LIW PROVIDER ERROR: CLiwServiceIfBase::InitialiseL() failed, leave code:%d"), err);
+#endif
+ }
+ }
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy(bind); // bind
+ }
+ }
+ return success; // returns status of 'n'th criteria in interest
+ }
+
+
+void CLiwServiceHandlerImpl::GetInterest(RCriteriaArray& aInterest)
+ {
+ for (TInt i = 0; i < iInterestList.Count(); i++)
+ {
+ if (aInterest.Append(iInterestList[i]) != KErrNone)
+ {
+ return;
+ }
+ }
+ }
+
+
+
+void CLiwServiceHandlerImpl::DetachL(const RCriteriaArray& aInterest)
+ {
+ // First, remove relevant criteria items from relevat base bindings.
+ for (TInt i = 0; i < aInterest.Count(); i++)
+ {
+ for (TInt j = 0; j < iBaseBindings.Count(); j++)
+ {
+ TInt index = iBaseBindings[j]->HasCriteriaItem(*aInterest[i]);
+ if (index != KErrNotFound)
+ {
+ iBaseBindings[j]->RemoveCriteria(index);
+ }
+ }
+ }
+
+ // Second pass removes empty bindings.
+ for (TInt i = 0; i < iBaseBindings.Count(); i++)
+ {
+ if (iBaseBindings[i]->Interest().Count() == 0)
+ {
+ delete iBaseBindings[i];
+ iBaseBindings.Remove(i);
+ i--;
+ }
+ }
+
+ // Then check if there were left obselete criteria items and remove them.
+ RemoveObsoleteCriteriaItems();
+
+ // Finally check if there were left obselete providers and remove them.
+ RemoveObsoleteProviders();
+ }
+
+
+
+void CLiwServiceHandlerImpl::DetachL(TInt aInterestResourceId)
+ {
+ // CCoeEnv/CEikonEnv needs to be accessible.
+ if(!iCoeEnv)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ RCriteriaArray interest;
+
+ CleanupStack::PushL( TCleanupItem( InterestCleanup, &interest ) );
+
+ TResourceReader reader;
+ iCoeEnv->CreateResourceReaderLC(reader, aInterestResourceId);
+ ReadInterestListL(reader, interest);
+ CleanupStack::PopAndDestroy(); //reader
+
+ DetachL( interest );
+
+ interest.ResetAndDestroy();
+ CleanupStack::Pop(&interest); // interest
+ }
+
+
+const CLiwCriteriaItem* CLiwServiceHandlerImpl::GetCriteria(TInt aId)
+ {
+ for (TInt i = 0; i < iInterestList.Count(); i++)
+ {
+ if (iInterestList[i]->Id() == aId)
+ {
+ return iInterestList[i];
+ }
+ }
+
+ return NULL;
+ }
+
+TInt CLiwServiceHandlerImpl::NumAlreadyInitializedPaneIdsL() const
+ {
+ TInt ret = 0;
+ TInt paneIds[KMaxPaneIds] = {0};
+ TBool found = EFalse;
+
+ for (TInt i = 0; i < iLastInitialized.Count(); i++)
+ {
+ found = EFalse;
+
+ for (TInt j = 0; j < ret; j++)
+ {
+ if (iLastInitialized[i]->MenuResourceId() == paneIds[j])
+ {
+ found = ETrue;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ // Create new item.
+ if (ret >= KMaxPaneIds)
+ {
+#ifdef _DEBUG
+ RDebug::Print(_L("ERROR: OVERFLOW in CLiwServiceHandlerImpl::NumAlreadyInitializedPaneIdsL()"));
+#endif
+ User::Leave(KErrOverflow);
+ }
+ paneIds[ret] = iLastInitialized[i]->MenuResourceId();
+ ret++;
+ }
+ }
+ return ret;
+ }
+
+void CLiwServiceHandlerImpl::InitializeMenuPaneL(
+ CEikMenuPane& aMenuPane,
+ TInt aMenuResourceId,
+ TInt aBaseMenuCmdId,
+ const CLiwGenericParamList& aInParamList)
+ {
+ InitializeMenuPaneL(aMenuPane, aMenuResourceId, aBaseMenuCmdId, aInParamList, EFalse);
+ }
+
+void CLiwServiceHandlerImpl::InitializeMenuPaneL(
+ CEikMenuPane& aMenuPane,
+ TInt aMenuResourceId,
+ TInt aBaseMenuCmdId,
+ const CLiwGenericParamList& aInParamList,
+ TBool aUseSubmenuTextsIfAvailable)
+ {
+ // CCoeEnv/CEikonEnv needs to be accessible.
+ if(!iCoeEnv)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ if (!iMenuBindings.Count())
+ {
+ // Either no menu is attached to interest or menu was attached but
+ // it didn't contain any placeholders for criteria items. So
+ // nothing to do, get out.
+ return;
+ }
+
+ TInt index;
+ TInt slotcmd;
+ TBuf <KMaxMenuTitleSize> subTitle;
+ TBool titleLocked;
+ TInt paneOffset = NumAlreadyInitializedPaneIdsL() * KIndividualMenuPaneIdRange;
+
+ iSubmenuCmd = aBaseMenuCmdId + KMenuPaneCommandRange;
+ slotcmd = SlotItemCmd(aMenuPane);
+ if (slotcmd >= 0)
+ {
+ // aMenuPane is liw submenu. At this point it is empty and we must
+ // copy provider menu items to it.
+ CLiwMenuPane* liwPane = MenuPaneForSlotCmd(slotcmd);
+ if (liwPane)
+ {
+ CopyMenuItemsL(liwPane, aMenuPane, 0, ETrue);
+ aMenuPane.DeleteMenuItem(slotcmd);
+ iSubmenu = liwPane;
+ }
+ }
+ else
+ {
+ iSubmenu = NULL;
+
+ const TInt bindcount = iMenuBindings.Count();
+ for (TInt i = 0; i < bindcount; i++)
+ {
+ if ((iMenuBindings[i]->MenuId() == aMenuResourceId) &&
+ (aMenuPane.MenuItemExists(iMenuBindings[i]->MenuCmd(), index)))
+ {
+ CLiwMenuPane* liwPane = iMenuBindings[i]->MenuPane();
+ TInt menuResourceId = -1;
+ if(liwPane)
+ {
+ // An LIW menu pane already exists (this means that a normal
+ // non-LIW submenu with LIW items has been opened more than once).
+ // In this case we use the existing resource slot id.
+ menuResourceId = liwPane->ResourceSlotId();
+ paneOffset = liwPane->PaneOffset();
+ DeleteLiwMenuPane(liwPane);
+ liwPane = NULL;
+ }
+ liwPane = CreateEmptyLiwMenuPaneL(aBaseMenuCmdId, menuResourceId);
+ CleanupStack::PushL(liwPane);
+ liwPane->SetPaneOffset(paneOffset);
+ paneOffset += KPlaceholderCmdIdRange;
+ iMenuBindings[i]->SetMenuPane(liwPane);
+
+ // Clean previous service commands from list.
+ CLiwGenericParamList& list = const_cast<CLiwGenericParamList&>(aInParamList);
+ while (list.Remove(EGenericParamServiceCommand))
+ {
+ // Intentionally left empty.
+ }
+
+ // Add service commands for current placeholder.
+ const TInt icount = iMenuBindings[i]->Interest().Count();
+ for (TInt k = 0; k < icount; k++)
+ {
+ list.AppendL(TLiwGenericParam(EGenericParamServiceCommand,
+ TLiwVariant(iMenuBindings[i]->Interest()[k]->ServiceCmd())));
+ }
+
+ // Loop from last entry to first entry always inserting to same index.
+ // Default provider is the first item in list, so if there is a default
+ // provider defined, it will be the first one to appear in menus.
+ for (TInt j = iMenuBindings[i]->NumberOfProviders() - 1; j >= 0; j--)
+ {
+ liwPane->SetInitializingOwner(iMenuBindings[i]->MenuProvider(j));
+ iMenuBindings[i]->MenuProvider(j)->InitializeMenuPaneHookL(liwPane,
+ 0, 0, aInParamList);
+ }
+
+ GetSubmenuTitle(liwPane->MenuPane(), subTitle);
+
+ TLiwPlaceholderType phtype = PlaceholderType(aMenuPane,
+ iMenuBindings[i]->MenuCmd(), titleLocked);
+
+ if ((phtype == ELiwPlaceholderCascade) ||
+ (phtype == ELiwPlaceholderIntelligentCascade))
+ {
+ if (liwPane->MenuPane().NumberOfItemsInPane() == 1)
+ {
+ // Remove placeholder item.
+ aMenuPane.DeleteMenuItem(iMenuBindings[i]->MenuCmd());
+ CleanupStack::PopAndDestroy(liwPane); // liwPane
+ continue;
+ }
+ else if ((liwPane->MenuPane().NumberOfItemsInPane() == 2) &&
+ (phtype == ELiwPlaceholderIntelligentCascade))
+ {
+ UnCascadeL(aMenuPane, iMenuBindings[i]->MenuCmd(), *liwPane);
+ User::LeaveIfError(iLastInitialized.Append(liwPane));
+ }
+ else
+ {
+ if (titleLocked)
+ {
+ subTitle.Zero();
+ }
+ ConvertPlaceholderL(aMenuPane, iMenuBindings[i]->MenuCmd(), *liwPane,
+ subTitle);
+ }
+ }
+ else
+ {
+ // Remove placeholder item.
+ aMenuPane.DeleteMenuItem(iMenuBindings[i]->MenuCmd());
+
+ // Copy menu items to actual menu pane
+ CopyMenuItemsL(liwPane, aMenuPane, index, aUseSubmenuTextsIfAvailable);
+ User::LeaveIfError(iLastInitialized.Append(liwPane));
+ }
+ liwPane->SetMenuResourceId(aMenuResourceId);
+ User::LeaveIfError(iMenuPanes.Append(liwPane));
+ CleanupStack::Pop(liwPane); // liwPane
+ }
+ }
+ }
+ }
+
+
+
+
+TInt CLiwServiceHandlerImpl::ServiceCmdByMenuCmd(TInt aMenuCmdId) const
+ {
+ for (TInt i = 0; i < iMenuBindings.Count(); i++)
+ {
+ if ((IsInLastInitialized(iMenuBindings[i]->MenuPane())) &&
+ (iMenuBindings[i]->MenuPane()->IsCmdInRange(KPlaceholderCmdIdRange, aMenuCmdId)))
+ {
+ return iMenuBindings[i]->MenuPane()->ServiceCmdId(aMenuCmdId);
+ }
+ }
+
+ return 0;
+ }
+
+
+
+void CLiwServiceHandlerImpl::ExecuteMenuCmdL(
+ TInt aMenuCmdId,
+ const CLiwGenericParamList& aInParamList,
+ CLiwGenericParamList& aOutParamList,
+ TUint aCmdOptions,
+ MLiwNotifyCallback* aCallback)
+ {
+ // CCoeEnv/CEikonEnv needs to be accessible.
+ if(!iCoeEnv)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ if (!iMenuBindings.Count())
+ {
+ return;
+ }
+
+ // Handle real menu providers.
+ for (TInt i = 0; i < iMenuBindings.Count(); i++)
+ {
+ CLiwMenuPane* menuPane = iMenuBindings[i]->MenuPane();
+
+ if (IsInLastInitialized(menuPane))
+ {
+ for (TInt j = 0; j < iMenuBindings[i]->NumberOfProviders(); j++)
+ {
+ if ((menuPane->IsCmdInRange(KPlaceholderCmdIdRange, aMenuCmdId)) &&
+ (menuPane->CommandOwner(aMenuCmdId) == iMenuBindings[i]->MenuProvider(j)))
+ {
+ iMenuBindings[i]->MenuProvider(j)->HandleMenuCmdHookL(
+ menuPane,
+ aMenuCmdId,
+ aInParamList,
+ aOutParamList,
+ aCmdOptions,
+ aCallback);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+
+
+void CLiwServiceHandlerImpl::AttachMenuL(TInt aMenuResourceId, TInt aInterestResourceId)
+ {
+ // CCoeEnv/CEikonEnv needs to be accessible.
+ if(!iCoeEnv)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ RCriteriaArray interest, filtered;
+ TResourceReader reader;
+
+ CleanupStack::PushL( TCleanupItem( InterestCleanup, &interest ) );
+ CleanupStack::PushL( TCleanupItem( FilteredCleanup, &filtered ) );
+ iCoeEnv->CreateResourceReaderLC(reader, aInterestResourceId);
+ ReadInterestListL(reader, interest);
+ CleanupStack::PopAndDestroy(); //reader
+ FilterInterestListL(interest, filtered);
+
+ iCoeEnv->CreateResourceReaderLC(reader, aMenuResourceId);
+ DoAttachMenuL(reader, aMenuResourceId, filtered);
+ filtered.Reset();
+ CleanupStack::PopAndDestroy(); //reader
+ CleanupStack::Pop(&filtered); // filtered
+ CleanupStack::Pop(&interest); // interest
+ }
+
+
+
+void CLiwServiceHandlerImpl::AttachMenuL(TInt aMenuResourceId, TResourceReader& aReader)
+ {
+ // CCoeEnv/CEikonEnv needs to be accessible.
+ if(!iCoeEnv)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ RCriteriaArray interest, filtered;
+ TResourceReader reader;
+
+ CleanupStack::PushL( TCleanupItem( InterestCleanup, &interest ) );
+ CleanupStack::PushL( TCleanupItem( FilteredCleanup, &filtered ) );
+ ReadInterestListL(aReader, interest);
+ FilterInterestListL(interest, filtered);
+
+ iCoeEnv->CreateResourceReaderLC(reader, aMenuResourceId);
+ DoAttachMenuL(reader, aMenuResourceId, filtered);
+ filtered.Reset();
+ CleanupStack::PopAndDestroy(); //reader
+ CleanupStack::Pop(&filtered); // filtered
+ CleanupStack::Pop(&interest); // interest
+ }
+
+void CLiwServiceHandlerImpl::AttachMenuL(TInt aMenuResourceId, const RCriteriaArray& aInterest)
+ {
+ // CCoeEnv/CEikonEnv needs to be accessible.
+ if(!iCoeEnv)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ RCriteriaArray interest, filtered;
+ TResourceReader reader;
+
+ CleanupStack::PushL( TCleanupItem( InterestCleanup, &interest ) );
+ CleanupStack::PushL( TCleanupItem( FilteredCleanup, &filtered ) );
+
+ for(TInt i = 0; i < aInterest.Count(); i++)
+ {
+ CLiwCriteriaItem* item = CLiwCriteriaItem::NewLC();
+
+ item->SetId( aInterest[i]->Id() );
+ item->SetServiceCmd( aInterest[i]->ServiceCmd() );
+ item->SetContentTypeL( aInterest[i]->ContentType() );
+ item->SetServiceClass( aInterest[i]->ServiceClass() );
+ item->SetOptions( aInterest[i]->Options() );
+ item->SetDefaultProvider( (aInterest[i]->DefaultProvider()).iUid );
+ item->SetMaxProviders( aInterest[i]->MaxProviders() );
+
+ User::LeaveIfError(interest.Append(item));
+ CleanupStack::Pop(item);
+ }
+
+ FilterInterestListL(interest, filtered);
+
+ iCoeEnv->CreateResourceReaderLC(reader, aMenuResourceId);
+ DoAttachMenuL(reader, aMenuResourceId, filtered);
+ filtered.Reset();
+ CleanupStack::PopAndDestroy(); //reader
+ CleanupStack::Pop(&filtered); // filtered
+ CleanupStack::Pop(&interest); // interest
+ }
+
+void CLiwServiceHandlerImpl::AttachMenuL(RArray<TInt>& aMenuEntries,
+ TInt aMenuResourceId,
+ RCriteriaArray& aInterest)
+ {
+ RCriteriaArray filtered;
+
+ CleanupStack::PushL( TCleanupItem( FilteredCleanup, &filtered ) );
+ FilterInterestListL(aInterest, filtered);
+
+ TInt menuCmd;
+ TInt count = aMenuEntries.Count();
+ TBool bound;
+
+ for (TInt i = 0; i < count; i++)
+ {
+ menuCmd = aMenuEntries[i];
+ CLiwMenuBinding* bind = NULL;
+ bound = EFalse;
+
+ if (!menuCmd)
+ continue;
+
+ for (TInt j = 0; j < filtered.Count(); j++)
+ {
+ if (filtered[j]->Id() == menuCmd)
+ {
+ if (!bind)
+ {
+ bind = AlreadyBound(aMenuResourceId, menuCmd, i);
+ if (!bind)
+ {
+ bind = CLiwMenuBinding::NewLC(i, aMenuResourceId);
+ bind->SetMenuCmd( menuCmd );
+ }
+ else
+ {
+ bound = ETrue;
+ }
+ }
+
+ if (bind->HasCriteriaItem(*(filtered[j])) == KErrNotFound)
+ {
+ ResolveProvidersL(bind, filtered[j],NULL);
+ bind->AddCriteriaL(filtered[j]);
+ }
+ }
+ }
+
+ // Initialise providers.
+ if (bind)
+ {
+ for (TInt k = 0; k < bind->NumberOfProviders(); k++)
+ {
+ bind->MenuProvider(k)->InitialiseL(*this, bind->Interest());
+ }
+ if (!bound)
+ {
+ User::LeaveIfError(iMenuBindings.Append( bind ));
+ CleanupStack::Pop(bind); // bind
+ }
+ }
+ }
+
+ filtered.Reset();
+ CleanupStack::Pop(&filtered); // filtered
+ }
+
+void CLiwServiceHandlerImpl::DoAttachMenuL(TResourceReader& aReader, TInt aMenuId,
+ RCriteriaArray& aInterest)
+ {
+ TInt menuCmd;
+ TInt count = aReader.ReadInt16();
+ TBool bound;
+
+ for (TInt i = 0; i < count; i++)
+ {
+ menuCmd = aReader.ReadInt32();
+ CLiwMenuBinding* bind = NULL;
+ bound = EFalse;
+
+ for (TInt j = 0; j < aInterest.Count(); j++)
+ {
+ if (aInterest[j]->Id() == menuCmd)
+ {
+ if (!bind)
+ {
+ bind = AlreadyBound(aMenuId, menuCmd, i);
+ if (!bind)
+ {
+ bind = CLiwMenuBinding::NewLC(i, aMenuId);
+ bind->SetMenuCmd( menuCmd );
+ }
+ else
+ {
+ bound = ETrue;
+ }
+ }
+
+ if (bind->HasCriteriaItem(*(aInterest[j])) == KErrNotFound)
+ {
+ ResolveProvidersL(bind, aInterest[j],NULL);
+ bind->AddCriteriaL(aInterest[j]);
+ }
+ }
+ }
+
+ // Initialise providers.
+ if (bind)
+ {
+ for (TInt k = 0; k < bind->NumberOfProviders(); k++)
+ {
+ TRAPD(err, bind->MenuProvider(k)->InitialiseL(*this, bind->Interest()));
+ if(err)
+ {
+#ifdef _DEBUG
+ RDebug::Print(_L("LIW PROVIDER ERROR: CLiwServiceIfMenu::InitialiseL() failed, leave code:%d"), err);
+#endif
+ // The provider failed to initialise.
+ // Remove the failed provider from this menu binding.
+ CLiwServiceIfMenu* provider = bind->MenuProvider(k);
+ TInt implUid = provider->ImplementationUid().iUid;
+ bind->RemoveProvider(implUid);
+
+ // Remove the failed provider also from other menu bindings.
+ for (TInt m = 0; m < iMenuBindings.Count(); m++)
+ {
+ iMenuBindings[m]->RemoveProvider(implUid);
+ }
+
+ // Then remove provider from the owner list and delete it.
+ for (TInt m = 0; m < iProviders.Count(); m++)
+ {
+ if (iProviders[m]->ImplementationUid().iUid == implUid)
+ {
+ delete iProviders[m];
+ iProviders.Remove(m);
+ m--;
+ }
+ }
+ }
+ }
+ if (!bound)
+ {
+ User::LeaveIfError(iMenuBindings.Append( bind ));
+ CleanupStack::Pop(bind); // bind
+ }
+ }
+ SkipMenuFields(aReader); // Jump to next menu item
+ }
+ }
+
+void CLiwServiceHandlerImpl::ReadInterestL(RCriteriaArray& aInterest, TInt aInterestResourceId)
+ {
+ CleanupStack::PushL( TCleanupItem( InterestCleanup, &aInterest ) );
+ TResourceReader reader;
+ iCoeEnv->CreateResourceReaderLC(reader, aInterestResourceId);
+ ReadInterestListL(reader, aInterest);
+ CleanupStack::PopAndDestroy(); //reader
+ CleanupStack::Pop(&aInterest);
+ }
+
+
+void CLiwServiceHandlerImpl::DetachMenu(TInt aMenuResourceId, TInt aInterestResourceId)
+ {
+ // If interest resource id is null, then detach all items in the given menu.
+ if (!aInterestResourceId)
+ {
+ DoDetachMenu(aMenuResourceId);
+ }
+ else
+ {
+ // CCoeEnv/CEikonEnv needs to be accessible.
+ if(!iCoeEnv)
+ {
+ // We cannot leave because this is a non-leaving method.
+ return;
+ }
+
+ RCriteriaArray interest;
+ TRAPD(err, ReadInterestL(interest, aInterestResourceId));
+ if (err)
+ {
+ return;
+ }
+
+ DoDetachMenu(aMenuResourceId, interest);
+
+ interest.ResetAndDestroy();
+ }
+ }
+
+
+void CLiwServiceHandlerImpl::DoDetachMenu(TInt aMenuResourceId)
+ {
+ // First, delete the relevant menu bindings.
+ for (TInt i = 0; i < iMenuBindings.Count(); i++)
+ {
+ if (iMenuBindings[i]->MenuId() == aMenuResourceId)
+ {
+ delete iMenuBindings[i];
+ iMenuBindings.Remove(i);
+ i--;
+ }
+ }
+
+ // Then check if there were left obselete criteria items and remove them.
+ RemoveObsoleteCriteriaItems();
+
+ // Finally check if there were left obselete providers and remove them.
+ RemoveObsoleteProviders();
+ }
+
+
+void CLiwServiceHandlerImpl::DoDetachMenu(TInt aMenuResourceId, RCriteriaArray& aInterest)
+ {
+ // First, remove relevant criteria items from relevant menu bindings.
+ for (TInt i = 0; i < iMenuBindings.Count(); i++)
+ {
+ if (iMenuBindings[i]->MenuId() == aMenuResourceId)
+ {
+ for (TInt j = 0; j < aInterest.Count(); j++)
+ {
+ TInt index = iMenuBindings[i]->HasCriteriaItem(*aInterest[j]);
+ if (index != KErrNotFound)
+ {
+ iMenuBindings[i]->RemoveCriteria(index);
+ }
+ }
+ }
+ }
+
+ // Second pass removes empty bindings.
+ for (TInt i = 0; i < iMenuBindings.Count(); i++)
+ {
+ if (iMenuBindings[i]->Interest().Count() == 0)
+ {
+ delete iMenuBindings[i];
+ iMenuBindings.Remove(i);
+ i--;
+ }
+ }
+
+ // Then check if there were left obselete criteria items and remove them.
+ RemoveObsoleteCriteriaItems();
+
+ // Finally check if there were left obselete providers and remove them.
+ RemoveObsoleteProviders();
+ }
+
+
+void CLiwServiceHandlerImpl::RemoveObsoleteCriteriaItems()
+ {
+ for (TInt i = 0; i < iInterestList.Count(); i++)
+ {
+ CLiwCriteriaItem* criteria = iInterestList[i];
+ TBool found = EFalse;
+
+ // Loop through base bindings.
+ for (TInt j = 0; j < iBaseBindings.Count(); j++)
+ {
+ if (iBaseBindings[j]->HasCriteriaItem(*criteria) != KErrNotFound)
+ {
+ found = ETrue;
+ break;
+ }
+ }
+
+ // If still not found, loop through menu bindings.
+ if (!found)
+ {
+ for (TInt j = 0; j < iMenuBindings.Count(); j++)
+ {
+ if (iMenuBindings[j]->HasCriteriaItem(*criteria) != KErrNotFound)
+ {
+ found = ETrue;
+ break;
+ }
+ }
+ }
+
+ // Criteria item can be deleted if it was not found.
+ if (!found)
+ {
+ delete iInterestList[i];
+ iInterestList.Remove(i);
+ i--;
+ }
+ }
+ }
+
+
+void CLiwServiceHandlerImpl::RemoveObsoleteProviders()
+ {
+ for (TInt i = 0; i < iProviders.Count(); i++)
+ {
+ CLiwServiceIfBase* provider = iProviders[i];
+ TBool found = EFalse;
+
+ // Loop through base bindings.
+ for (TInt j = 0; j < iBaseBindings.Count(); j++)
+ {
+ if (iBaseBindings[j]->HasProvider(provider))
+ {
+ found = ETrue;
+ break;
+ }
+ }
+
+ // If still not found, loop through menu bindings.
+ if (!found)
+ {
+ for (TInt j = 0; j < iMenuBindings.Count(); j++)
+ {
+ if (iMenuBindings[j]->HasProvider(provider))
+ {
+ found = ETrue;
+ break;
+ }
+ }
+ }
+
+ // Criteria item can be deleted if it was not found.
+ if (!found)
+ {
+ delete iProviders[i];
+ iProviders.Remove(i);
+ i--;
+ }
+ }
+ }
+
+
+TBool CLiwServiceHandlerImpl::IsSubMenuEmpty(TInt aSubMenuId)
+ {
+ for (TInt i = 0; i < iMenuBindings.Count(); i++)
+ {
+ if (iMenuBindings[i]->MenuId() == aSubMenuId)
+ {
+ if (iMenuBindings[i]->NumberOfProviders() > 0)
+ {
+ return EFalse;
+ }
+
+ return ETrue;
+ }
+ }
+
+ return EFalse;
+ }
+
+
+
+
+CLiwMenuBinding* CLiwServiceHandlerImpl::AlreadyBound(TInt aMenuId, TInt aMenuCmd,
+ TInt aMenuItemIndex) const
+ {
+ for (TInt i = 0; i < iMenuBindings.Count(); i++)
+ {
+ if ((iMenuBindings[i]->MenuId() == aMenuId) &&
+ (iMenuBindings[i]->MenuCmd() == aMenuCmd) &&
+ (iMenuBindings[i]->MenuItemIndex() == aMenuItemIndex))
+ {
+ return iMenuBindings[i];
+ }
+ }
+
+ return NULL;
+ }
+
+
+void CLiwServiceHandlerImpl::ExecuteServiceCmdL(
+ const TInt& aCmdId,
+ const CLiwGenericParamList& aInParamList,
+ CLiwGenericParamList& aOutParamList,
+ TUint aCmdOptions,
+ MLiwNotifyCallback* aCallback)
+ {
+ for (TInt i = 0; i < iBaseBindings.Count(); i++)
+ {
+ if(iBaseBindings[i]->HasServiceCmd(aCmdId))
+ {
+ for (TInt j = 0; j < iBaseBindings[i]->NumberOfProviders(); j++)
+ {
+ iBaseBindings[i]->BaseProvider(j)->HandleServiceCmdL(aCmdId,
+ aInParamList, aOutParamList, aCmdOptions, aCallback);
+ }
+ }
+ }
+}
+
+void CLiwServiceHandlerImpl::ExecuteServiceCmdL(
+ const CLiwCriteriaItem& aCmd,
+ const CLiwGenericParamList& aInParamList,
+ CLiwGenericParamList& aOutParamList,
+ TUint aCmdOptions,
+ MLiwNotifyCallback* aCallback)
+ {
+ for (TInt i = 0; i < iBaseBindings.Count(); i++) {
+ for (TInt k = 0; k < iBaseBindings[i]->Interest().Count(); k++) {
+ if ((iBaseBindings[i]->Interest()[k]->ServiceCmd() == KLiwCmdAsStr) &&
+ (aCmd.ServiceCmd() == KLiwCmdAsStr) &&
+ (iBaseBindings[i]->Interest()[k]->ServiceCmdStr() == aCmd.ServiceCmdStr()) &&
+ (iBaseBindings[i]->Interest()[k]->ContentType() == aCmd.ContentType()))
+ {
+ //call only one provider
+ if (iBaseBindings[i]->NumberOfProviders() > 0) {
+ iBaseBindings[i]->BaseProvider(0)->HandleServiceCmdL(aCmd.ServiceCmdStr(),
+ aInParamList, aOutParamList, aCmdOptions, aCallback);
+ }
+ }
+ }
+ }
+ }
+
+void CLiwServiceHandlerImpl::ReadInterestListL(TResourceReader& aReader,
+ RPointerArray<CLiwCriteriaItem>& aResult)
+ {
+ const TInt count = aReader.ReadInt16();
+ for (TInt ii = 0; ii < count; ++ii)
+ {
+ CLiwCriteriaItem* item = CLiwCriteriaItem::NewLC();
+ item->ReadFromResoureL( aReader );
+ User::LeaveIfError(aResult.Append(item));
+ CleanupStack::Pop(item); // item
+ }
+ }
+
+/* Parses the metadata information stored in the opaque_data field
+ * of service provider registration information \c REGISTRY_INFO.
+ *
+ * The metadata information is seprated from the service command definition
+ * in the opaque_data field using a separator "::".
+ *
+ * @param aOpaque the opaque_data values specified in the registration information
+ * @param aMetaData the parsed metadata entries will be stored in this variable
+ *
+ */
+void CLiwServiceHandlerImpl::ParseMetaData(const TDesC8& aOpaque, TDes8& aMetaData)
+ {
+
+ _LIT8(serviceCmdSeparator, "::");
+ const TInt metaDataStartPos=2;
+
+ TInt separatorPos = aOpaque.Find(serviceCmdSeparator);
+
+ if (separatorPos != KErrNotFound)
+ {
+ // Find the first section, up to the separator
+ separatorPos += metaDataStartPos;
+ aMetaData.Copy(aOpaque.Mid(separatorPos,aOpaque.Length()-separatorPos));
+ }
+ }
+
+/*
+ QueryImplementationL finds the providers that match the given criteria item that is passed as the parameters
+*/
+void CLiwServiceHandlerImpl::QueryImplementationL(CLiwCriteriaItem* aItem, RCriteriaArray& aProviderList)
+ {
+ RImplInfoPtrArray infoArray;
+ _LIT8(KWild,"*");
+
+ if(0 == aItem->ContentType().Compare(KNullDesC8))
+ aItem->SetContentTypeL(KWild);
+
+ if(0 == aItem->ServiceCmdStr().Compare(KNullDesC8))
+ aItem->SetServiceCmdL(KWild);
+
+ //to fetch the infoArray
+ QueryImplementationL(aItem,infoArray);
+
+ CLiwXmlHandler* pXmlHandler = CLiwXmlHandler::NewLC();
+
+ CLiwServiceData* pServiceData = NULL;
+
+ TInt versionCheck = 0;
+
+ for (TInt index = 0; index < infoArray.Count(); ++index)
+ {
+ if ((aItem->Options() & LIW_OPTIONS_ROM_ONLY) && (infoArray[index]->RomBased() == EFalse))
+ {
+ continue;
+ }
+
+ CImplementationInformation* pImplInfo = infoArray[index];
+ const TInt separatorLength = KDataSeparator().Length();//find "||"
+ TInt separatorPos = pImplInfo->OpaqueData().Find(KDataSeparator);
+
+ TInt leftExtractPos = 0;
+ TBool separatorFound = EFalse;
+
+ do
+ {
+ //Constructing the Criteria Item and appending to providerList
+ CLiwCriteriaItem* item = CLiwCriteriaItem::NewLC(); //iCriteriaId & iServiceCmd are ignored...
+ item->SetServiceClass(TUid::Uid(KLiwClassBase));
+ item->SetContentTypeL(infoArray[index]->DataType());
+
+ TBuf8<KMaxLength> sName;
+ TBuf8<KMaxLength> opaq;
+
+ if(separatorPos != KErrNotFound && (leftExtractPos < separatorPos))
+ {
+ separatorFound = ETrue;
+ sName = pImplInfo->OpaqueData().Mid(leftExtractPos, separatorPos-leftExtractPos); //ServiceName
+ leftExtractPos = separatorLength + separatorPos;
+ TPtrC8 remainingData = pImplInfo->OpaqueData().Mid(separatorPos + separatorLength);
+ separatorPos = remainingData.Find(KDataSeparator) + separatorPos + separatorLength;
+ }
+ else
+ {
+ separatorFound = EFalse;
+ TInt mDataSepPos = pImplInfo->OpaqueData().Find(serviceCmdSeparator);
+ if(mDataSepPos != KErrNotFound)
+ sName = pImplInfo->OpaqueData().Mid(leftExtractPos, mDataSepPos - leftExtractPos);
+ else
+ sName = pImplInfo->OpaqueData().Mid(leftExtractPos);
+ }
+
+ //check for wildcard character *
+ //if yes, return immediatly
+ if(0 == aItem->ServiceCmdStr().Compare(sName) || 0 == aItem->ServiceCmdStr().Compare(KWild))
+ {
+ //parse metadata and if metadata valid,
+ //setmetadataoptions to criteriaitem..
+ pServiceData = CLiwServiceData::NewLC();
+ TInt loadStatus = CLiwXmlHandler::ESrvDataLoadFailed;
+
+ ParseMetaData(pImplInfo->OpaqueData(),opaq);
+
+ //Inline metadata defined
+ if(opaq.Length()>0)
+ {
+ loadStatus=pXmlHandler->LoadServiceData(opaq,pServiceData);
+ }
+ else
+ {
+ //Obtain the capabilities from the metadata
+ TUid implUid = pImplInfo->ImplementationUid();
+ TUidName srvProvUid = implUid.Name();
+
+ TPtrC16 ptrSrv = srvProvUid.Right(srvProvUid.Length()-1);
+ TPtrC16 srvFile = ptrSrv.Left(ptrSrv.Length()-1);
+ TDriveUnit driveUnit = pImplInfo->Drive();
+ TFileName fileName = driveUnit.Name();
+ fileName.Append(KDC_RESOURCE_FILES_DIR);
+ fileName.Append(srvFile);
+ fileName.Append(KPerExtension);
+ loadStatus=pXmlHandler->LoadServiceData(fileName,pServiceData);
+ }
+
+ if(CLiwXmlHandler::ESrvDataLoadSuccess==loadStatus)
+ {
+ versionCheck = 0;
+
+ TReal implVersion(KDefVersion);
+ this->ComputeIntfVersion(pServiceData,implVersion); //fetch impl version..
+
+ TReal minVer(KDefVersion);
+ TReal maxVer(KUnspVersion);
+
+ if(this->GetVersionRange(aItem,minVer,maxVer)) //Get version queried by consumer
+ {
+ if(minVer == KUnspVersion)
+ minVer = KDefVersion;
+
+ //perform comparison...
+ if(maxVer!=KUnspVersion)
+ {
+ if((implVersion>=minVer) && (implVersion<=maxVer))
+ {
+ versionCheck = 1;
+ //current impl is the best choice..this is THE CHOSEN ONE..
+ }
+ }
+ else
+ {
+ //means maxVer == KUnspVersion
+ if(implVersion>=minVer)
+ {
+ versionCheck = 1;
+
+ //current impl is the best choice..this is THE CHOSEN ONE..
+ }
+ }
+ }
+ }
+ else //means no metadata information
+ {
+ versionCheck = 1;
+ }
+
+ if(versionCheck)
+ {
+ //Since version matches, this item is appended to the providerList
+ //before which the metadata information is SET
+ CLiwMap* metadataMap = CLiwDefaultMap::NewLC();
+
+ CLiwGenericParamList* pMetaData = pServiceData->GetMetaData();
+
+ for(TInt mdataIdx(0); mdataIdx<pMetaData->Count(); ++mdataIdx)
+ {
+ TLiwGenericParam param;
+ pMetaData->AtL(mdataIdx,param);
+ metadataMap->InsertL(param.Name(),param.Value());
+ param.Reset();
+ }
+
+ TLiwVariant mdataVar(metadataMap);
+ mdataVar.PushL();
+
+ item->SetMetaDataOptions(mdataVar);
+
+ item->SetServiceCmdL(sName);
+ CleanupStack::Pop(&mdataVar);
+ mdataVar.Reset();
+
+ CleanupStack::Pop(metadataMap);
+ metadataMap->DecRef();
+
+ User::LeaveIfError(aProviderList.Append(item));
+ }
+
+ if(pServiceData)
+ pServiceData->CleanUpMetaData();
+
+ CleanupStack::PopAndDestroy(pServiceData); //pServiceData::CLiwServiceData*
+ CleanupStack::Pop(item); //item::CLiwCriteriaItem*
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy(item); //item::CLiwCriteriaItem*
+ }
+ }while(separatorFound);
+ }// end of outer for loop
+
+ CleanupStack::PopAndDestroy(pXmlHandler); //pXmlHandler::CLiwXMLHandler*
+ infoArray.ResetAndDestroy();
+ }
+
+
+void CLiwServiceHandlerImpl::QueryImplementationL(CLiwCriteriaItem* aItem, RImplInfoPtrArray& infoArray)
+ {
+ iEcomMonitor->ListImplemetationsL(infoArray, (CLiwCriteriaItem*)aItem);
+ }
+
+
+void CLiwServiceHandlerImpl::FilterInfoArray(RImplInfoPtrArray& aArray,
+ RArray<TInt32>& aArrayPlugin,
+ CLiwCriteriaItem* aItem)
+ {
+ if (aItem->MaxProviders() <= 0)
+ {
+ aArray.ResetAndDestroy();
+ aArrayPlugin.Reset();
+ }
+ else
+ {
+ while ((aArray.Count() + aArrayPlugin.Count()) > aItem->MaxProviders())
+ {
+ if (aArrayPlugin.Count() == 0)
+ break;
+ // Skip default provider.
+ if (aArrayPlugin[0] == aItem->DefaultProvider())
+ {
+ if (aArrayPlugin.Count() == 1)
+ break;
+ aArrayPlugin.Remove(1);
+ }
+ else
+ {
+ aArrayPlugin.Remove(0);
+ }
+ }
+
+ while ((aArray.Count() + aArrayPlugin.Count()) > aItem->MaxProviders())
+ {
+ // Skip default provider.
+ if (aArray[0]->ImplementationUid() == aItem->DefaultProvider())
+ {
+ delete aArray[1];
+ aArray.Remove(1);
+ }
+ else
+ {
+ delete aArray[0];
+ aArray.Remove(0);
+ }
+ }
+ }
+ }
+
+
+
+TBool CLiwServiceHandlerImpl::IsCached(CLiwServiceIfBase* /*aProvider*/)
+ {
+ return EFalse;
+ }
+
+
+CLiwGenericParamList& CLiwServiceHandlerImpl::InParamListL()
+ {
+ if (!iInParams)
+ {
+ iInParams = CLiwGenericParamList::NewL();
+ }
+ iInParams->Reset();
+ return *iInParams;
+ }
+
+
+
+CLiwGenericParamList& CLiwServiceHandlerImpl::OutParamListL()
+ {
+ if (!iOutParams)
+ {
+ iOutParams = CLiwGenericParamList::NewL();
+ }
+ iOutParams->Reset();
+ return *iOutParams;
+ }
+
+
+
+TBool CLiwServiceHandlerImpl::IsInLastInitialized(CLiwMenuPane* liwPane) const
+ {
+ if (liwPane)
+ {
+ if (iSubmenu == liwPane)
+ {
+ return ETrue;
+ }
+
+ for (TInt i = 0; i < iLastInitialized.Count(); i++)
+ {
+ if (iLastInitialized[i] == liwPane)
+ {
+ return ETrue;
+ }
+ }
+ }
+
+ return EFalse;
+ }
+
+
+TInt CLiwServiceHandlerImpl::HandleNotifyL(
+ TInt /*aCmdId*/,
+ TInt /*aEventId*/,
+ CLiwGenericParamList& /*aEventParamList*/,
+ const CLiwGenericParamList& /*aInParamList*/)
+ {
+ return KErrNone;
+ }
+
+
+// CEikMenuPane::ConstructFromresourceL is defined as 'protected' so
+// we have to use a wrapper class for accessing it.
+class CLiwMenuResource : public CEikMenuPane
+ {
+ public:
+ CLiwMenuResource() : CEikMenuPane(NULL) {}
+ CLiwMenuResource(MEikMenuObserver* aObserver) : CEikMenuPane(aObserver) {}
+
+ void CreateL(TResourceReader& aReader)
+ {
+ ConstructFromResourceL(aReader);
+ }
+ };
+
+
+CLiwMenuPane* CLiwServiceHandlerImpl::CreateEmptyLiwMenuPaneL(TInt aBaseMenuCmdId,
+ TInt aResourceId)
+ {
+ CLiwMenuPane* result = NULL;
+ TResourceReader reader;
+
+ TInt id;
+ if(aResourceId >= 0)
+ {
+ // Use existing id.
+ id = aResourceId;
+ }
+ else
+ {
+ // Create new id.
+ id = ResourceIdForNextFreeSlot();
+ if (id < 0)
+ {
+ User::Leave(KErrOverflow);
+ }
+ }
+ iCoeEnv->CreateResourceReaderLC(reader, id);
+
+ CLiwMenuResource* pane = new (ELeave) CLiwMenuResource(this);
+ CleanupStack::PushL(pane);
+ pane->ConstructL(NULL);
+ pane->CreateL(reader);
+
+ result = new (ELeave) CLiwMenuPane(*pane, aBaseMenuCmdId);
+
+ CleanupStack::Pop(pane);
+ CleanupStack::PopAndDestroy(); //reader
+
+ result->SetResourceSlotId( id );
+
+ return result;
+ }
+
+
+void CLiwServiceHandlerImpl::DeleteLiwMenuPane(CLiwMenuPane* aLiwPane)
+ {
+ delete aLiwPane->iMenuPane;
+ aLiwPane->iMenuPane = NULL;
+
+ // Reset iIdMap and extraText.
+ for(TInt i = 0; i < aLiwPane->iIdMap.Count(); i++)
+ {
+ aLiwPane->iIdMap[i].extraText.Close();
+ }
+ aLiwPane->iIdMap.Reset();
+
+ // Remove the liw menu pane from iMenuPanes array.
+ for(TInt i = 0; i < iMenuPanes.Count(); i++)
+ {
+ if(iMenuPanes[i] == aLiwPane)
+ {
+ iMenuPanes.Remove(i);
+ break;
+ }
+ }
+
+ // Remove the liw menu pane from iMenuLastInitialized array.
+ for(TInt i = 0; i < iLastInitialized.Count(); i++)
+ {
+ if(iLastInitialized[i] == aLiwPane)
+ {
+ iLastInitialized.Remove(i);
+ break;
+ }
+ }
+
+ delete aLiwPane;
+ aLiwPane = NULL;
+ }
+
+const TInt resourceSlotIds[KMaxMenuResources] =
+ {
+ R_LIW_EMPTY_MENU_0,
+ R_LIW_EMPTY_MENU_1,
+ R_LIW_EMPTY_MENU_2,
+ R_LIW_EMPTY_MENU_3,
+ R_LIW_EMPTY_MENU_4,
+ R_LIW_EMPTY_MENU_5,
+ R_LIW_EMPTY_MENU_6,
+ R_LIW_EMPTY_MENU_7,
+ R_LIW_EMPTY_MENU_8,
+ R_LIW_EMPTY_MENU_9,
+ R_LIW_EMPTY_MENU_10,
+ R_LIW_EMPTY_MENU_11,
+ R_LIW_EMPTY_MENU_12,
+ R_LIW_EMPTY_MENU_13,
+ R_LIW_EMPTY_MENU_14,
+ R_LIW_EMPTY_MENU_15
+ };
+
+
+TInt CLiwServiceHandlerImpl::ResourceIdForNextFreeSlot()
+ {
+ if (iNextFreeSlot < KMaxMenuResources)
+ {
+ return resourceSlotIds[iNextFreeSlot++];
+ }
+
+ return -1;
+ }
+
+
+void CLiwServiceHandlerImpl::SetEmphasis(CCoeControl* /*aMenuControl*/,TBool /*aEmphasis*/)
+ {
+ }
+
+
+void CLiwServiceHandlerImpl::ProcessCommandL(TInt /*aCommandId*/)
+ {
+ }
+
+
+// Rewrite this method. It doesn't make sense. Variable j is not used at all.
+TInt CLiwServiceHandlerImpl::MenuCmdId(TInt aMenuCmdId) const
+ {
+ TInt ret( KErrNotFound );
+
+ for (TInt i = 0; i < iMenuBindings.Count() && (ret == KErrNotFound); i++)
+ {
+ for (TInt j = 0; j < iMenuBindings[i]->NumberOfProviders() && (ret == KErrNotFound); j++)
+ {
+ if ((IsInLastInitialized(iMenuBindings[i]->MenuPane())) &&
+ (iMenuBindings[i]->MenuPane()->IsCmdInRange(KPlaceholderCmdIdRange, aMenuCmdId)) &&
+ (ret == KErrNotFound ))
+ {
+ ret = iMenuBindings[i]->MenuPane()->MenuCmdId(aMenuCmdId);
+ }
+ }
+ }
+
+ return ret;
+ }
+
+
+void Cleanup( TAny* aAny )
+ {
+ RImplInfoPtrArray* implArray =
+ reinterpret_cast< RImplInfoPtrArray*> ( aAny );
+ implArray->ResetAndDestroy();
+ implArray->Close();
+ }
+
+
+void InterestCleanup( TAny* aAny )
+ {
+ RPointerArray<CLiwCriteriaItem>* interestArray =
+ reinterpret_cast<RPointerArray<CLiwCriteriaItem>*> ( aAny );
+
+ interestArray->ResetAndDestroy();
+ }
+
+void FilteredCleanup( TAny* aAny )
+ {
+ RPointerArray<CLiwCriteriaItem>* filteredArray =
+ reinterpret_cast<RPointerArray<CLiwCriteriaItem>*> ( aAny );
+
+ filteredArray->Reset();
+ }
+
+
+void IntArrayCleanup(TAny* aAny)
+ {
+ RArray<TInt>* intArray =
+ reinterpret_cast<RArray<TInt>*> ( aAny );
+
+ intArray->Close();
+ }
+
+void Int32ArrayCleanup(TAny* aAny)
+ {
+ RArray<TInt32>* intArray =
+ reinterpret_cast<RArray<TInt32>*> ( aAny );
+
+ intArray->Close();
+ }
+
+void InterfaceCleanup( TAny* aAny )
+ {
+ MLiwInterface* interface = reinterpret_cast<MLiwInterface*>(aAny);
+ interface->Close();
+ }
+
+void CLiwServiceHandlerImpl::CopyMenuItemsL(CLiwMenuPane* aSource, CEikMenuPane& aDest,
+ TInt aStartIndex, TBool aIsSubmenu)
+ {
+ TInt cmdId;
+ TInt inPos = aStartIndex;
+
+ for (TInt i = 0; i < aSource->MenuPane().NumberOfItemsInPane(); i++)
+ {
+ cmdId = aSource->FindCmdId(i);
+ if (cmdId >= 0)
+ {
+ CEikMenuPaneItem::SData itemData = aSource->MenuPane().ItemData(cmdId);
+
+ // The menu item might include alternative texts for a main menu level
+ // and for submenu. Use submenu string if it is intended so.
+ if(aIsSubmenu)
+ {
+ const TDesC& extraText = aSource->ExtraText(cmdId);
+ if(extraText.Length())
+ {
+ itemData.iText.Zero();
+ itemData.iText.Append(extraText);
+ }
+ }
+
+ aDest.InsertMenuItemL(itemData, inPos++);
+ }
+ }
+ }
+
+
+
+TInt CLiwServiceHandlerImpl::SlotItemCmd(CEikMenuPane& aPane)
+ {
+ TInt index;
+
+ for (TInt i = 0; i < KMaxMenuResources; i++)
+ {
+ if (aPane.MenuItemExists(ELiwMenuSlotBase + i, index))
+ {
+ return ELiwMenuSlotBase + i;
+ }
+ }
+
+ return -1;
+ }
+
+
+
+CLiwMenuPane* CLiwServiceHandlerImpl::MenuPaneForSlotCmd(TInt aCmdId)
+ {
+ TInt index = aCmdId - ELiwMenuSlotBase;
+
+ if (index < KMaxMenuResources)
+ {
+ TInt resId = resourceSlotIds[index];
+ for (TInt i = 0; i < iMenuPanes.Count(); i++)
+ {
+ if (iMenuPanes[i]->ResourceSlotId() == resId)
+ {
+ return iMenuPanes[i];
+ }
+ }
+ }
+
+ return NULL;
+ }
+
+
+
+CLiwServiceHandlerImpl::TLiwPlaceholderType CLiwServiceHandlerImpl::PlaceholderType(
+ CEikMenuPane& aPane, TInt aCmd, TBool& aTitleLocked)
+ {
+ CEikMenuPaneItem::SData& itemData = aPane.ItemData(aCmd);
+
+ aTitleLocked = EFalse;
+
+ if ((itemData.iCascadeId & LIW_CASCADE_ID) == LIW_CASCADE_ID)
+ {
+ if (itemData.iCascadeId & LIW_LOCK_SUBMENU_TITLE)
+ {
+ aTitleLocked = ETrue;
+ }
+ return ELiwPlaceholderCascade;
+ }
+ else if ((itemData.iCascadeId & LIW_INTELLIGENT_CASCADE_ID) == LIW_INTELLIGENT_CASCADE_ID)
+ {
+ if (itemData.iCascadeId & LIW_LOCK_SUBMENU_TITLE)
+ {
+ aTitleLocked = ETrue;
+ }
+ return ELiwPlaceholderIntelligentCascade;
+ }
+
+ return ELiwPlaceholderNormal;
+ }
+
+
+
+void CLiwServiceHandlerImpl::ConvertPlaceholderL(CEikMenuPane& aPane, TInt aCmd,
+ CLiwMenuPane& aLiwPane, const TDesC& aTitle)
+ {
+ CEikMenuPaneItem::SData itemData = aPane.ItemData(aCmd);
+ TInt index;
+
+ // Remenber index.
+ aPane.MenuItemExists(aCmd, index);
+
+ // Remove placeholder item.
+ aPane.DeleteMenuItem(aCmd);
+
+ // Replace liw cascade id with actual menu resource id.
+ itemData.iCascadeId = aLiwPane.iResourceSlotId;
+
+ if (aTitle.Length())
+ {
+ itemData.iText.Copy(aTitle);
+ }
+
+ // Set unused dynamic cmd id.
+ itemData.iCommandId = iSubmenuCmd++;
+
+ // Insert cascade item.
+ aPane.InsertMenuItemL(itemData, index);
+ }
+
+
+
+void CLiwServiceHandlerImpl::UnCascadeL(CEikMenuPane& aPane, TInt aCmd, CLiwMenuPane& aLiwPane)
+ {
+ CEikMenuPaneItem::SData itemData = aLiwPane.MenuPane().ItemData(aLiwPane.FindCmdId(0));
+ TInt index;
+
+ // Remenber index.
+ aPane.MenuItemExists(aCmd, index);
+
+ // Remove placeholder item.
+ aPane.DeleteMenuItem(aCmd);
+
+ // Uncascade
+ itemData.iCascadeId = 0;
+
+ // Insert cascade item.
+ aPane.InsertMenuItemL(itemData, index);
+ }
+
+
+
+void CLiwServiceHandlerImpl::SkipMenuFields(TResourceReader& aReader)
+ {
+ aReader.ReadInt32(); // Skip cascade id
+ aReader.ReadInt32(); // Skip flags
+ aReader.ReadTPtrC(); // Skip text
+ aReader.ReadTPtrC(); // Skip extra text
+ aReader.ReadTPtrC(); // Skip bmpfile.
+ aReader.ReadInt16(); // Skip bmpid.
+ aReader.ReadInt16(); // Skip bmpmask.
+ aReader.ReadInt32(); // Skip extension.
+ }
+
+
+TBool CLiwServiceHandlerImpl::IsLiwMenu(TInt aMenuResourceId)
+ {
+ TInt index;
+
+ // First check if this is liw submenu id
+ for (index = 0; index < KMaxMenuResources; index++)
+ {
+ if (aMenuResourceId == resourceSlotIds[index])
+ {
+ return ETrue;
+ }
+ }
+
+ // Then check if this menu is among attached menus.
+ for (index = 0; index < iMenuBindings.Count(); index++)
+ {
+ if (iMenuBindings[index]->MenuId() == aMenuResourceId)
+ {
+ return ETrue;
+ }
+ }
+
+ return EFalse;
+ }
+
+
+
+TBool CLiwServiceHandlerImpl::HandleSubmenuL(CEikMenuPane& aPane)
+ {
+ TInt slotcmd = SlotItemCmd(aPane);
+ if (slotcmd >= 0)
+ {
+ // aPane is liw submenu. At this point it is empty and we must
+ // copy provider menu items to it.
+ CLiwMenuPane* liwPane = MenuPaneForSlotCmd(slotcmd);
+ if (liwPane)
+ {
+ CopyMenuItemsL(liwPane, aPane, 0, ETrue);
+ aPane.DeleteMenuItem(slotcmd);
+ iSubmenu = liwPane;
+ return ETrue;
+ }
+ }
+
+ return EFalse;
+ }
+
+
+
+TBool CLiwServiceHandlerImpl::GetSubmenuTitle(CEikMenuPane& aPane, TDes& aResult)
+ {
+ TInt index;
+
+ aResult.Zero();
+ while (aPane.MenuItemExists(LIW_SUBMENU_TITLE, index))
+ {
+ CEikMenuPaneItem::SData& itemData = aPane.ItemData(LIW_SUBMENU_TITLE);
+ if (aResult.Length() == 0)
+ {
+ aResult.Copy(itemData.iText);
+ }
+ aPane.DeleteMenuItem(LIW_SUBMENU_TITLE);
+ return ETrue;
+ }
+
+ return EFalse;
+ }
+
+
+
+CLiwCriteriaItem* CLiwServiceHandlerImpl::ConvertCriteriaItemPointerL(CLiwCriteriaItem* aCandidate)
+ {
+ for (TInt index = 0; index < iInterestList.Count(); index++)
+ {
+ if ((*iInterestList[index]) == (*aCandidate))
+ {
+ // Already in list, aCandidate is not needed.
+ delete aCandidate;
+ return iInterestList[index];
+ }
+ }
+
+ CleanupStack::PushL(aCandidate);
+ User::LeaveIfError(iInterestList.Append(aCandidate));
+ CleanupStack::Pop(aCandidate); // aCandidate
+
+ return aCandidate;
+ }
+
+
+
+void CLiwServiceHandlerImpl::FilterInterestListL(RPointerArray<CLiwCriteriaItem>& aOrginal,
+ RPointerArray<CLiwCriteriaItem>& aFiltered)
+ {
+ CLiwCriteriaItem* item;
+
+ while (aOrginal.Count() > 0)
+ {
+ item = aOrginal[0];
+ aOrginal.Remove(0);
+ item = ConvertCriteriaItemPointerL(item);
+ User::LeaveIfError(aFiltered.Append(item));
+ }
+ aOrginal.Reset();
+ }
+
+
+
+void CLiwServiceHandlerImpl::RemoveProvider(TInt aImplUid)
+ {
+ TInt index;
+
+ // First go through bindings and remove all the
+ // references to given provider.
+ for (index = 0; index < iBaseBindings.Count(); index++)
+ {
+ iBaseBindings[index]->RemoveProvider(aImplUid);
+ }
+
+ for (index = 0; index < iMenuBindings.Count(); index++)
+ {
+ iMenuBindings[index]->RemoveProvider(aImplUid);
+ }
+
+ // Then remove provider from the owner list and delete it.
+ for (index = 0; index < iProviders.Count(); index++)
+ {
+ if (iProviders[index]->ImplementationUid().iUid == aImplUid)
+ {
+ delete iProviders[index];
+ iProviders.Remove(index);
+ index--;
+ }
+ }
+ }
+
+
+void CLiwServiceHandlerImpl::AddProviderL(TUid aImplUid, CLiwCriteriaItem* aItem)
+ {
+ TInt index;
+ CLiwServiceIfBase* iface = iEcomMonitor->CreateImplementationL(aImplUid);
+
+ if (iface)
+ {
+ CleanupStack::PushL(iface);
+ iface->AddCriteria(aItem);
+ User::LeaveIfError(iProviders.Append( iface ));
+ CleanupStack::Pop(iface);
+
+ for (index = 0; index < iBaseBindings.Count(); index++)
+ {
+ if (iBaseBindings[index]->HasCriteriaItem(*aItem) != KErrNotFound)
+ {
+ iBaseBindings[index]->AddProviderL(iface, aImplUid == aItem->DefaultProvider());
+ iface->InitialiseL(*this, iBaseBindings[index]->Interest());
+ }
+ }
+
+ for (index = 0; index < iMenuBindings.Count(); index++)
+ {
+ if (iMenuBindings[index]->HasCriteriaItem(*aItem) != KErrNotFound)
+ {
+ iMenuBindings[index]->AddProviderL(iface, aImplUid == aItem->DefaultProvider());
+ iface->InitialiseL(*this, iMenuBindings[index]->Interest());
+ }
+ }
+ }
+ }
+
+
+
+TInt CLiwServiceHandlerImpl::SynchronizeCallBack(TAny* aImpl)
+ {
+ CLiwServiceHandlerImpl* impl = reinterpret_cast<CLiwServiceHandlerImpl*>(aImpl);
+ TRAPD(err, impl->SynchronizeDbL());
+ return err;
+ }
+
+
+
+void CLiwServiceHandlerImpl::SynchronizeDbL()
+ {
+ TInt index;
+ RArray<TInt> providers;
+ RImplInfoPtrArray infoArray;
+
+ CleanupStack::PushL( TCleanupItem( IntArrayCleanup, &providers ) );
+ CleanupStack::PushL( TCleanupItem( Cleanup, &infoArray ) );
+
+ for (index = 0; index < iInterestList.Count(); index++)
+ {
+ if (iInterestList[index]->RomOnly()) // Rom-only criterias can be skipped.
+ {
+ continue;
+ }
+
+ providers.Reset();
+ infoArray.ResetAndDestroy();
+ ListProvidersForCriteriaL(providers, *(iInterestList[index]));
+ iEcomMonitor->ListImplemetationsL(infoArray, iInterestList[index]);
+ HandleRemovedProviders(providers, infoArray);
+ HandleNewProvidersL(providers, infoArray, iInterestList[index]);
+ }
+
+ CleanupStack::PopAndDestroy(&infoArray); // providers, infoArray
+ CleanupStack::PopAndDestroy(&providers);
+ }
+
+
+void CLiwServiceHandlerImpl::HandleRemovedProviders(RArray<TInt>& aInMemory,
+ RImplInfoPtrArray& aInSystem)
+ {
+ TInt index, index2;
+
+ for (index = 0; index < aInMemory.Count(); index++)
+ {
+ for (index2 = 0; index2 < aInSystem.Count(); index2++)
+ {
+ if (aInSystem[index2]->ImplementationUid().iUid == aInMemory[index])
+ {
+ break;
+ }
+ }
+ if (index2 >= aInSystem.Count()) // Was removed from system.
+ {
+ RemoveProvider(aInMemory[index]);
+ }
+ }
+ }
+
+
+void CLiwServiceHandlerImpl::HandleNewProvidersL(RArray<TInt>& aInMemory,
+ RImplInfoPtrArray& aInSystem, CLiwCriteriaItem* aItem)
+ {
+ TInt index;
+
+ for (index = 0; index < aInSystem.Count(); index++)
+ {
+ if (aInMemory.Find(aInSystem[index]->ImplementationUid().iUid) == KErrNotFound)
+ {
+ AddProviderL(aInSystem[index]->ImplementationUid(), aItem);
+ }
+ }
+ }
+
+void CLiwServiceHandlerImpl::MenuLaunched()
+ {
+ ClearMenuPaneArray();
+ iNextFreeSlot = 0;
+ iLastInitialized.Reset();
+
+ // Reset the iMenuPane pointers from iMenuBindings.
+ for(TInt index = 0; index < iMenuBindings.Count(); index++)
+ {
+ iMenuBindings[index]->SetMenuPane(NULL);
+ }
+ }
+
+/* Utility function to get the symbian TCapability enum value
+ * from the string defined in the providers xml file
+ *
+ * @param aCapName name of the capabiility to be converted to \c TCapability enum
+ *
+ */
+
+TCapability CLiwServiceHandlerImpl::GetServiceCapability(const TDesC& aCapName)
+{
+ TCapability cap(ECapability_None);
+
+ if(0==aCapName.Compare(KCapabilityCommDD))
+ {
+ cap=ECapabilityCommDD;
+ }
+ else if(0==aCapName.Compare(KCapabilityPowerMgmt))
+ {
+ cap=ECapabilityPowerMgmt;
+ }
+ else if(0==aCapName.Compare(KCapabilityMultimediaDD))
+ {
+ cap=ECapabilityMultimediaDD;
+ }
+ else if(0==aCapName.Compare(KCapabilityReadDeviceData))
+ {
+ cap=ECapabilityReadDeviceData;
+ }
+ else if(0==aCapName.Compare(KCapabilityWriteDeviceData))
+ {
+ cap=ECapabilityWriteDeviceData;
+ }
+ else if(0==aCapName.Compare(KCapabilityDRM))
+ {
+ cap=ECapabilityDRM;
+ }
+ else if(0==aCapName.Compare(KCapabilityTrustedUI))
+ {
+ cap=ECapabilityTrustedUI;
+ }
+ else if(0==aCapName.Compare(KCapabilityProtServ))
+ {
+ cap=ECapabilityProtServ;
+ }
+ else if(0==aCapName.Compare(KCapabilityDiskAdmin))
+ {
+ cap=ECapabilityDiskAdmin;
+ }
+ else if(0==aCapName.Compare(KCapabilityNetworkControl))
+ {
+ cap=ECapabilityNetworkControl;
+ }
+ else if(0==aCapName.Compare(KCapabilityAllFiles))
+ {
+ cap=ECapabilityAllFiles;
+ }
+ else if(0==aCapName.Compare(KCapabilitySwEvent))
+ {
+ cap=ECapabilitySwEvent;
+ }
+ else if(0==aCapName.Compare(KCapabilityNetworkServices))
+ {
+ cap=ECapabilityNetworkServices;
+ }
+ else if(0==aCapName.Compare(KCapabilityLocalServices))
+ {
+ cap=ECapabilityLocalServices;
+ }
+ else if(0==aCapName.Compare(KCapabilityReadUserData))
+ {
+ cap=ECapabilityReadUserData;
+ }
+ else if(0==aCapName.Compare(KCapabilityWriteUserData))
+ {
+ cap=ECapabilityWriteUserData;
+ }
+ else if(0==aCapName.Compare(KCapabilityLocation))
+ {
+ cap=ECapabilityLocation;
+ }
+ else if(0==aCapName.Compare(KCapabilitySurroundingsDD))
+ {
+ cap=ECapabilitySurroundingsDD;
+ }
+ else if(0==aCapName.Compare(KCapabilityUserEnvironment))
+ {
+ cap=ECapabilityUserEnvironment;
+ }
+
+ return cap;
+}
+
+
+/**
+* Returns the capability set defined in the service provider
+* metadata information. The capability set is a pre-requisite
+* for the service consumer to load the service provider module.
+*
+* The capability metadata information are defined as XML character
+* data inside the element <capability/>. The capability information
+* are type of metadata information. Hence, the capability element tags
+* should appear as child element of <metadata> element.
+*
+* @param aCapability Capability set that the consumer should posess while
+* loading the service provider
+*
+* @example
+*
+* @code
+* <!-- consumer should posess the following capability set -->
+* <metadata>
+* <capability>CapabilityReadUserData</capability>
+* <capability>CapabilityWriteUserData</capability>
+* <capability>CapabilityDRM</capability>
+* </metadata>
+* @endcode
+*
+*/
+
+void CLiwServiceHandlerImpl::GetCapabilitiesL(RArray<TCapability>& secMgrCapList,CLiwGenericParamList* pMetaData)
+{
+ _LIT8(KCapability,"cap");
+
+ TInt pos = 0;
+ const TLiwGenericParam* pCapData = pMetaData->FindFirst(pos,KCapability);
+
+ if(pCapData)
+ {
+ const CLiwList* pCapList = pCapData->Value().AsList();
+ if(pCapList)
+ {
+ for(TInt idx(0);idx!=pCapList->Count();++idx)
+ {
+ TLiwVariant capVar;
+ capVar.PushL();
+ pCapList->AtL(idx, capVar);
+ TPtrC capStr = capVar.AsDes();
+
+ TCapability cap = this->GetServiceCapability(capStr);
+ if( (cap>=ECapabilityTCB) && (cap < ECapability_Limit))
+ secMgrCapList.AppendL(cap);
+ CleanupStack::Pop(&capVar);
+ capVar.Reset();
+ }
+ }
+
+ }
+}
+
+void CLiwServiceHandlerImpl::ComputeIntfVersion(CLiwServiceData* pProvMetaData,TReal& aIntfVersion)
+{
+ CLiwGenericParamList* pMetaDataList = pProvMetaData->GetMetaData();
+
+ if(pMetaDataList)
+ {
+ TInt verPos(KErrNone);
+ _LIT8(KVer,"ver");
+ const TLiwGenericParam* pVerParam = pMetaDataList->FindFirst(verPos,KVer);
+ if(pVerParam)
+ {
+ const CLiwList* pVersionList = pVerParam->Value().AsList();
+ if(pVersionList)
+ {
+ if(pVersionList->Count())
+ {
+ TLiwVariant verVar;
+ verVar.PushL();
+ pVersionList->AtL(0,verVar);//pick up the value in 0th index..
+ aIntfVersion = verVar.AsTReal();
+ CleanupStack::Pop(&verVar);
+ verVar.Reset();
+ }
+ }
+ }
+ }
+}
+
+
+TInt CLiwServiceHandlerImpl::ResolveProvidersL(CLiwBinding* aBinding,
+ CLiwCriteriaItem* aItem,
+ CRTSecMgrScriptSession* aScriptSession)
+ {
+ TInt result = 0;
+ TInt status = KLiwUnknown;
+
+ // First resolve for providers already in memory.
+ TInt index;
+ for (index = 0; index < iProviders.Count(); index++)
+ {
+ if (iProviders[index]->Match(aItem))
+ {
+ aBinding->AddProviderL((CLiwServiceIfBase*)iProviders[index],
+ iProviders[index]->ImplementationUid() == aItem->DefaultProvider());
+ result++;
+ }
+ }
+
+
+ // If cached providers were found, then it means that all the matching
+ // providers must be already in memory. No need to query from ECom framework.
+ if (!result)
+ {
+ RImplInfoPtrArray infoArray;
+ RArray<TInt32> infoArrayPlugin;
+
+ CleanupStack::PushL( TCleanupItem( Cleanup, &infoArray ) );
+ CleanupStack::PushL( TCleanupItem( Int32ArrayCleanup, &infoArrayPlugin ) );
+
+ iEcomMonitor->ListImplemetationsL(infoArray, aItem);
+
+ FilterInfoArray(infoArray, infoArrayPlugin, aItem);
+
+ CLiwServiceData* pServiceData = NULL;
+
+ CLiwServiceData* pPrevSData = NULL;
+
+ CImplementationInformation* pChosenImpl = NULL;
+
+ TReal currentMax(KDefVersion);
+
+ for (index = 0; index < infoArray.Count(); index++)
+ {
+ TBool stackPop = EFalse;
+ if ((aItem->Options() & LIW_OPTIONS_ROM_ONLY) && (infoArray[index]->RomBased() == EFalse))
+ {
+ continue;
+ }
+
+ //Check whether consumer has capability
+ //mandated by provider
+ CImplementationInformation* pImplInfo = infoArray[index];
+
+ TBuf8<KMaxLength> opaq;
+
+ ParseMetaData(pImplInfo->OpaqueData(),opaq);
+
+ CLiwXmlHandler* pXmlHandler = CLiwXmlHandler::NewLC();
+
+ pServiceData = CLiwServiceData::NewLC();
+
+ TInt loadStatus= CLiwXmlHandler::ESrvDataLoadFailed;
+
+ //Inline metadata defined
+ if(opaq.Length()>0)
+ {
+ loadStatus=pXmlHandler->LoadServiceData(opaq,pServiceData);
+ }
+ else
+ {
+ //Obtain the capabilities from the metadata
+ TUid implUid = pImplInfo->ImplementationUid();
+ TUidName srvProvUid = implUid.Name();
+
+
+ TPtrC16 ptrSrv = srvProvUid.Right(srvProvUid.Length()-1);
+ TPtrC16 srvFile = ptrSrv.Left(ptrSrv.Length()-1);
+ TDriveUnit driveUnit = pImplInfo->Drive();
+ TFileName fileName = driveUnit.Name();
+ fileName.Append(KDC_RESOURCE_FILES_DIR);
+ fileName.Append(srvFile);
+ fileName.Append(KPerExtension);
+ loadStatus=pXmlHandler->LoadServiceData(fileName,pServiceData);
+ }
+
+ /*
+ * - Get version range specified by the consumer
+ * - Iterate over the list of intf impl
+ *
+ * //LOOP:
+ * - For each implementation item,
+ *
+ * - Check if intf impl has version tag from its metadata
+ * - Pick up interface impl's version tag
+ * - If intf impl has NO specifed version tag
+ * - set this intf impl version as DEFAULT VERSION (//pref 1.0)..
+ *
+ * //CHOOSE LATEST VERSION:
+ * - If consumer has specifed version range
+ * - CALL COMPARE routine (//To check if this is the latest version so far)
+ * - Mark this as the chosen implementation
+ * - Else (//This is NOT the latest)
+ * - Continue;
+ *
+ * - Else (//If consumer did not specify version range)
+ * - CALL COMPARE routine (//To check if this is the latest version so far)
+ * - Mark this as the chosen implementation
+ * - Else (//This is NOT the latest)
+ * - Continue;
+ *
+ * //COMPARE (currentMax,implVersion,minVer,maxVer): //default minVer=1.0
+ * - if(implVersion>currentMax)
+ * - if(implVersion>=minVer && implVersion<=maxVer)
+ * - currentMax = implVersion;
+ * - return; //mark pServiceData to point to the current impl's service data
+ * - else
+ * - return; //leave pServiceData as it is
+ * - else
+ * - return; //leave pServiceData as it is
+ *
+ */
+
+ if(CLiwXmlHandler::ESrvDataLoadSuccess==loadStatus) //metadata is parsed successfully
+ {
+ TReal implVersion(KDefVersion);
+ this->ComputeIntfVersion(pServiceData,implVersion); //fetch impl version..
+
+ TReal minVer(KDefVersion);
+ TReal maxVer(KUnspVersion);
+
+ TBool verChk = this->GetVersionRange(aItem,minVer,maxVer);
+
+ if(verChk) //Get version queried by consumer
+ {
+ if(minVer == KUnspVersion)
+ minVer = KDefVersion;
+
+ //perform comparison...
+ if(implVersion>=currentMax)
+ {
+ if(maxVer!=KUnspVersion)
+ {
+ if((implVersion>=minVer) && (implVersion<=maxVer))
+ {
+ currentMax = implVersion;
+ pChosenImpl = infoArray[index];
+ //current impl is the best choice..this is THE CHOSEN ONE..
+ if(pPrevSData)
+ {
+ pPrevSData->CleanUpMetaData();
+ delete pPrevSData;
+
+ }
+
+ pPrevSData = pServiceData;
+
+ }
+ else
+ {
+ //current impl is NOT THE RIGHT CHOICE.. since not within the range
+ if(pServiceData)
+ {
+ if(!stackPop)
+ {
+ stackPop = ETrue;
+ CleanupStack::Pop(pServiceData);
+ }
+ pServiceData->CleanUpMetaData();
+ delete pServiceData;
+ pServiceData = NULL;
+ }
+ status = KLiwVersionOutOfRange;
+ }
+ }
+ else
+ {
+ //means maxVer == KUnspVersion
+ if(implVersion>=minVer)
+ {
+ currentMax = implVersion;
+ pChosenImpl = infoArray[index];
+
+ //current impl is the best choice..this is THE CHOSEN ONE..
+ if(pPrevSData)
+ {
+ pPrevSData->CleanUpMetaData();
+ delete pPrevSData;
+ }
+
+ pPrevSData = pServiceData;
+ }
+ else
+ {
+ //current impl is NOT THE RIGHT CHOICE..
+ if(pServiceData)
+ {
+ if(!stackPop)
+ {
+ stackPop = ETrue;
+ CleanupStack::Pop(pServiceData);
+ }
+ pServiceData->CleanUpMetaData();
+ delete pServiceData;
+ pServiceData = NULL;
+ }
+
+ status = KLiwVersionOutOfRange;
+ }
+ }
+ }
+ else
+ {
+ //current impl is NOT THE RIGHT CHOICE..since implVer > maxVer
+ if(pServiceData)
+ {
+ if(!stackPop)
+ {
+ stackPop = ETrue;
+ CleanupStack::Pop(pServiceData);
+ }
+ pServiceData->CleanUpMetaData();
+ delete pServiceData;
+ pServiceData = NULL;
+ }
+
+ status = KLiwVersionOutOfRange;
+ }
+ }
+ else
+ {
+ //GetVersionRange Fails..
+ //abort service resolution process..
+ if(pServiceData)
+ {
+ if(!stackPop)
+ {
+ stackPop = ETrue;
+ CleanupStack::Pop(pServiceData);
+ }
+ pServiceData->CleanUpMetaData();
+ delete pServiceData;
+ pServiceData = NULL;
+ }
+
+ status = KLiwInvalidVersionSpecification;
+ }
+
+ //other cases like parse error, capability not
+ //specified in meta data are handled
+
+ if(currentMax == implVersion)
+ {
+ if(pPrevSData && (pPrevSData!=pServiceData)) //just in case...
+ {
+ pPrevSData->CleanUpMetaData();
+ delete pPrevSData;
+ pPrevSData = NULL;
+ }
+ }
+ else
+ {
+ if(!stackPop)
+ {
+ stackPop = ETrue;
+ CleanupStack::Pop(pServiceData);
+ }
+ pServiceData = pPrevSData;
+ }
+ }
+ else
+ {
+ //Metadata specification not found.. Hence Load Fails
+ if(CLiwXmlHandler::ESrvDataFileNotFnd==loadStatus)
+ {
+ pChosenImpl = infoArray[index];
+ }
+ else //Some error like parse error, capability not specified are handled
+ {
+ if(pServiceData)
+ {
+ if(!stackPop)
+ {
+ stackPop = ETrue;
+ CleanupStack::Pop(pServiceData);
+ }
+ pServiceData->CleanUpMetaData();
+ delete pServiceData;
+ pServiceData = NULL;
+ }
+
+ status = KLiwMetaDataInvalidFormat;
+ }
+ }
+
+ for (TInt idx = 0; idx < infoArrayPlugin.Count(); idx++)
+ {
+ // currently assumed that implementations managed by plugins cannot be in ROM
+ if (aItem->Options() & LIW_OPTIONS_ROM_ONLY)
+ {
+ continue;
+ }
+ }
+
+ if(!stackPop)
+ {
+ CleanupStack::Pop(pServiceData);
+ }
+
+ CleanupStack::Pop(pXmlHandler);
+
+ if(pXmlHandler)
+ {
+ delete pXmlHandler;
+ }
+
+
+ } //end of for loop
+
+ if(pChosenImpl)
+ {
+ RArray<TCapability> provCaps;
+ GetCapabilitiesL(provCaps,pServiceData->GetMetaData());
+
+ TInt isAllowed(KErrNone);
+
+ if(aScriptSession)
+ isAllowed = aScriptSession->IsAllowed(provCaps);
+
+ if(KErrNone==isAllowed)
+ {
+ CLiwServiceIfBase* iface = iEcomMonitor->CreateImplementationL(
+ pChosenImpl->ImplementationUid());
+
+ if (iface)
+ {
+ if(pServiceData)
+ {
+ iface->iReserved=pServiceData;
+ }
+
+
+ if (!IsCached(iface))
+ {
+ CleanupStack::PushL(iface);
+ status = KLiwServiceLoadSuccess;
+ iface->AddCriteria(aItem);
+ User::LeaveIfError(iProviders.Append( iface ));
+ CleanupStack::Pop(iface);
+
+ aBinding->AddProviderL(iface,
+ pChosenImpl->ImplementationUid() == aItem->DefaultProvider());
+ }
+ else
+ {
+ delete iface;
+ iface = NULL;
+ }
+ }
+
+ }
+ else
+ {
+ status = KLiwSecurityAccessCheckFailed;
+
+ if(pServiceData)
+ {
+ pServiceData->CleanUpMetaData();
+ delete pServiceData;
+ pServiceData = NULL;
+ }
+
+ //enhancement : Should assign this to the previous service data
+ }
+
+ provCaps.Close();
+ }
+ else
+ {
+ //No Chosen implementation..
+
+ if(pServiceData) //This should ideally fail always
+ {
+ pServiceData->CleanUpMetaData();
+ delete pServiceData;
+ pServiceData = NULL;
+ }
+ }
+
+ if(0 == infoArray.Count())
+ status = KLiwUnknown;
+
+ CleanupStack::PopAndDestroy(2);//infoArray and infoArrayPlugin
+ }
+ else
+ {
+ status = KLiwServiceAlreadyLoaded;
+ }
+
+ return status;
+
+ }
+
+
+TBool CLiwServiceHandlerImpl::GetVersionRange(CLiwCriteriaItem* aItem,TReal& aMinVersion, TReal& aMaxVersion)
+{
+ TBool bFailed=EFalse;
+ TLiwVariant metaDataVar;
+ metaDataVar.PushL();
+
+ aItem->GetMetaDataOptions(metaDataVar);
+
+ const CLiwMap* metaDataMap = metaDataVar.AsMap();
+
+ if(metaDataMap)
+ {
+ _LIT8(KRangeKey,"range");
+ TLiwVariant rangeVar;
+ rangeVar.PushL();
+
+ if(metaDataMap->FindL(KRangeKey, rangeVar))
+ {
+ const CLiwList* pRangeList = rangeVar.AsList();
+ if(pRangeList)
+ {
+ TLiwVariant verCheck;
+ verCheck.PushL();
+ _LIT8(KVersion,"ver");
+ pRangeList->AtL(0,verCheck);
+
+ if(EVariantTypeDesC8==verCheck.TypeId())
+ {
+ if(0==KVersion().CompareF(verCheck.AsData()))
+ {
+ TLiwVariant minVerVar, maxVerVar;
+ minVerVar.PushL();
+ maxVerVar.PushL();
+
+ pRangeList->AtL(1,minVerVar);
+ aMinVersion = minVerVar.AsTReal();
+
+ if(minVerVar.AsTReal() < KDefVersion)
+ bFailed = ETrue;
+
+ pRangeList->AtL(2,maxVerVar);
+ aMaxVersion = maxVerVar.AsTReal();
+
+ if(maxVerVar.AsTReal() < aMinVersion && maxVerVar.AsTReal() != KUnspVersion)
+ bFailed = ETrue;
+
+ CleanupStack::Pop(&maxVerVar);
+ CleanupStack::Pop(&minVerVar);
+ minVerVar.Reset();
+ maxVerVar.Reset();
+ }
+ }
+ CleanupStack::Pop(&verCheck);
+ verCheck.Reset();
+ }
+ }
+ CleanupStack::Pop(&rangeVar);
+ rangeVar.Reset();
+ }
+
+ CleanupStack::Pop(&metaDataVar);
+ metaDataVar.Reset();
+
+ return !bFailed;
+}
+
+TBool CLiwServiceHandlerImpl::GetVersion(CLiwCriteriaItem* aItem,TReal& aVersion)
+{
+ TBool bFailed=EFalse;
+ TLiwVariant metaDataVar;
+ metaDataVar.PushL();
+
+ aItem->GetMetaDataOptions(metaDataVar);
+
+ const CLiwMap* metaDataMap = metaDataVar.AsMap();
+
+ if(metaDataMap)
+ {
+ _LIT8(KExactKey,"exact");
+ TLiwVariant exactVar;
+ exactVar.PushL();
+
+ if(metaDataMap->FindL(KExactKey, exactVar))
+ {
+ const CLiwList* pExactList = exactVar.AsList();
+ if(pExactList)
+ {
+ TLiwVariant verCheck;
+ verCheck.PushL();
+ _LIT8(KVersion,"ver");
+ pExactList->AtL(0,verCheck);
+
+ if(EVariantTypeDesC8==verCheck.TypeId())
+ {
+ if(0==KVersion().CompareF(verCheck.AsData()))
+ {
+ TLiwVariant versionVar;
+ versionVar.PushL();
+
+ pExactList->AtL(1,versionVar);
+
+ if((versionVar.AsTReal()) < KDefVersion)
+ {
+ bFailed = ETrue;
+ }
+
+ aVersion = versionVar.AsTReal();
+ CleanupStack::Pop(&versionVar);
+ versionVar.Reset();
+ }
+ }
+ CleanupStack::Pop(&verCheck);
+ verCheck.Reset();
+ }
+ }
+
+ CleanupStack::Pop(&exactVar);
+ exactVar.Reset();
+ }
+
+ CleanupStack::Pop(&metaDataVar);
+ metaDataVar.Reset();
+
+ return !bFailed;
+}
+
+// End of file