--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/provider/protocol/src/ncdprotocolimpl.cpp Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,1479 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Implementation of CNcdProtocol
+*
+*/
+
+
+#include "ncdprotocolimpl.h"
+#include "ncdparserfactory.h"
+#include "ncdparser.h"
+#include "ncdsessionhandler.h"
+#include "catalogsdebug.h"
+#include "ncdrequestbase.h"
+#include "ncddeviceinteractionfactory.h"
+#include "ncddeviceservice.h"
+#include "ncdrequestconfiguration.h"
+#include "ncdrequestconfigurationdata.h"
+#include "catalogssmsutils.h"
+#include "catalogscontext.h"
+#include "ncdkeyvaluemap.h"
+#include "ncdutils.h"
+#include "ncdstoragemanager.h"
+#include "ncdproviderdefines.h"
+#include "ncdstorage.h"
+#include "ncdconfigurationmanager.h"
+#include "ncdprotocoldefaultobserverimpl.h"
+#include "catalogsutils.h"
+#include "ncd_cp_cookieimpl.h"
+#include "ncd_cp_detailimpl.h"
+#include "ncdinternalconfigurationkeys.h"
+#include "ncdcapabilities.h"
+#include "ncdserverdetails.h"
+#include "catalogsuids.h"
+#include "ncdproviderutils.h"
+#include "ncdengineconfiguration.h"
+#include "ncdinstallationserviceimpl.h"
+#include "ncdprotocolstrings.h"
+#include "catalogs_device_config.h"
+
+ // Hardcoded platforminfo
+
+_LIT( KPlatformInfo, "Series60" );
+
+// ---------------------------------------------------------------------------
+// CContextData::CContextData
+// ---------------------------------------------------------------------------
+//
+CNcdProtocol::CContextData::CContextData( const MCatalogsContext& aContext,
+ CNcdSessionHandler* aSessionHandler ) : CBase(),
+ iFamilyId( aContext.FamilyId() ),
+ iSessionHandler( aSessionHandler )
+ {
+ }
+
+// ---------------------------------------------------------------------------
+// CContextData::~CContextData
+// ---------------------------------------------------------------------------
+//
+CNcdProtocol::CContextData::~CContextData()
+ {
+ delete iSessionHandler;
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// CContextData::SessionHandler
+// ---------------------------------------------------------------------------
+//
+MNcdSessionHandler& CNcdProtocol::CContextData::SessionHandler() const
+ {
+ DASSERT( iSessionHandler );
+ return *iSessionHandler;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CContextData::Context
+// ---------------------------------------------------------------------------
+//
+TUid CNcdProtocol::CContextData::FamilyId() const
+ {
+ return iFamilyId;
+ }
+
+// ---------------------------------------------------------------------------
+// CContextData::SessionL
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::CContextData::SessionL( const TDesC& aSessionId,
+ const TDesC& aServerUri, const TDesC& aNameSpace )
+ {
+ DLTRACEIN(( _L("Session Id: %S, server URI: %S, name space: %S"),
+ &aSessionId, &aServerUri, &aNameSpace ));
+
+ // Remove old session if any
+ iSessionHandler->RemoveSession( aServerUri, aNameSpace );
+
+ // Create a new session
+ DLTRACE( ( "Creating a new session" ) );
+ iSessionHandler->CreateSessionL( aServerUri, aNameSpace, aSessionId );
+
+ DLTRACEOUT(( "" ));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CNcdProtocol::CNcdProtocol( MNcdConfigurationManager& aConfigurationManager,
+ CNcdSubscriptionManager& aSubscriptionManager ) :
+ iConfigurationManager( aConfigurationManager ),
+ iSubscriptionManager( aSubscriptionManager )
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CNcdProtocol::~CNcdProtocol()
+ {
+ DLTRACEIN((""));
+ delete iSmsUtils;
+
+ iContexts.ResetAndDestroy();
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// NewL
+// ---------------------------------------------------------------------------
+//
+CNcdProtocol* CNcdProtocol::NewL( MNcdConfigurationManager& aConfigurationManager,
+ CNcdSubscriptionManager& aSubscriptionManager )
+ {
+ CNcdProtocol* self = new(ELeave) CNcdProtocol( aConfigurationManager,
+ aSubscriptionManager );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// ConstructL
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::ConstructL()
+ {
+ DLTRACEIN((""));
+ iSmsUtils = CCatalogsSmsUtils::NewL();
+ iDeviceService = &CNcdProviderUtils::DeviceService();
+
+ // This gets the firmware string and appends it with the variant
+ // string
+ iDeviceService->AppendVariantToFirmwareL(
+ CNcdProviderUtils::FileSession() );
+
+ // Get home MCC and MNC so they don't have to be acquired separately
+ // for every session
+ iDeviceService->HomeNetworkInfoL( iHomeMcc, iHomeMnc );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CreateParserL
+// ---------------------------------------------------------------------------
+//
+MNcdParser* CNcdProtocol::CreateParserL( MCatalogsContext& aContext,
+ const TDesC& aServerUri )
+ {
+ CContextData& data = CreateContextDataL( aContext );
+
+ // Create default observer
+ CNcdProtocolDefaultObserver* protocolDefaultObserver =
+ CNcdProtocolDefaultObserver::NewL( aContext,
+ iConfigurationManager,
+ iSubscriptionManager,
+ aServerUri );
+
+ CleanupStack::PushL( protocolDefaultObserver );
+
+ // Ownership of the default observer is transferred
+ MNcdParser* parser = NcdParserFactory::CreateParserL(
+ protocolDefaultObserver );
+
+ CleanupStack::Pop( protocolDefaultObserver );
+
+
+ // Set all default observers here! Clients may override them.
+ parser->Observers().SetSessionObserver( &data );
+
+ CleanupDeletePushL( parser );
+ // The following is used in session observer callback,
+ // and entityreference building:
+ parser->SetOriginL( aServerUri );
+
+ CleanupStack::Pop( parser );
+ return parser;
+ }
+
+// ---------------------------------------------------------------------------
+// Preminet protocol request processor
+// ---------------------------------------------------------------------------
+//
+HBufC8* CNcdProtocol::ProcessPreminetRequestL(
+ const MCatalogsContext& aContext,
+ CNcdRequestBase& aRequest, const TDesC& aServerUri,
+ TBool aForceConfigurationData )
+ {
+ DLTRACEIN((""));
+
+ // Get or create context data for the context
+ CContextData& contextData( CreateContextDataL( aContext ) );
+ HBufC* nameSpace = aRequest.NamespaceLC();
+ TBool sessionExists =
+ contextData.SessionHandler().DoesSessionExist( aServerUri, *nameSpace );
+
+ if ( aForceConfigurationData || !sessionExists )
+ {
+ DLTRACE(( _L("Session starts for server: %S, ns: %S"), &aServerUri,
+ nameSpace ));
+ CNcdRequestConfigurationData* config =
+ CNcdRequestConfigurationData::NewLC();
+
+ aRequest.SetConfigurationL( config );
+ CleanupStack::Pop( config );
+
+ // Common common processing for the request: add client-info etc.
+ AddClientInfoToRequestL( aContext, *config );
+
+ // Add engine's client-info
+ AddEngineClientInfoToRequestL( *config );
+
+ // Array for the cookies that are sent to the server
+ RPointerArray<MNcdConfigurationProtocolCookie> cookies;
+ CleanupResetAndDestroyPushL( cookies );
+
+ // Add CGW cookies if there are any
+ TBool cookiesChanged = AddCookiesL(
+ aContext,
+ cookies,
+ aServerUri,
+ *nameSpace );
+
+ // Add CDB cookies, these override existing server cookies
+ cookiesChanged |= AddCookiesL(
+ aContext,
+ cookies,
+ iConfigurationManager.MasterServerAddressL( aContext ),
+ NcdProviderDefines::KConfigNamespace );
+
+ // Finally add the cookies to the request
+ AddCookiesToRequestL( aRequest, cookies );
+
+ CleanupStack::PopAndDestroy( &cookies );
+
+ // Remove expired cookies from db
+ if ( cookiesChanged )
+ {
+ DLTRACE(("Cookies had expired, update the config to db"));
+ iConfigurationManager.SaveConfigurationToDbL( aContext );
+ }
+ }
+
+ if ( sessionExists )
+ {
+ // Set session id for a continuing session
+ aRequest.SetSessionL( contextData.SessionHandler().Session(
+ aServerUri, *nameSpace ) );
+ }
+ CleanupStack::PopAndDestroy( nameSpace );
+ HBufC8* req = aRequest.CreateRequestL();
+ DLINFO(("request=%S",req));
+ DLTRACEOUT((""));
+ return req;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Configuration protocol request processor
+// ---------------------------------------------------------------------------
+//
+HBufC8* CNcdProtocol::ProcessConfigurationRequestL(
+ const MCatalogsContext& aContext,
+ CNcdRequestConfiguration& aRequest )
+ {
+ DLTRACEIN((""));
+ // Get or create context data for the context
+ CContextData& contextData( CreateContextDataL( aContext ) );
+
+ CNcdRequestConfigurationData* config =
+ CNcdRequestConfigurationData::NewLC();
+
+ aRequest.SetConfigurationL( config );
+ CleanupStack::Pop( config );
+
+
+ // Common common processing for the request: add client-info etc.
+ AddClientInfoToRequestL( aContext, *config );
+
+ // Add engine's client-info
+ AddEngineClientInfoToRequestL( *config );
+
+ // Array for the cookies that are sent to the server
+ RPointerArray<MNcdConfigurationProtocolCookie> cookies;
+ CleanupResetAndDestroyPushL( cookies );
+
+ // Add cookies if there any
+ TBool cookiesChanged = AddCookiesL( aContext,
+ cookies,
+ iConfigurationManager.MasterServerAddressL( aContext ),
+ NcdProviderDefines::KConfigNamespace );
+
+ AddCookiesToConfigRequestL( *config, cookies );
+ CleanupStack::PopAndDestroy( &cookies );
+
+ // Remove expired cookies from db
+ if ( cookiesChanged )
+ {
+ DLTRACE(("Cookies had expired, update the config to db"));
+ iConfigurationManager.SaveConfigurationToDbL( aContext );
+ }
+
+ HBufC8* req = aRequest.CreateRequestL();
+ //DLINFO(("request=%S",req));
+ DLTRACEOUT((""));
+ return req;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Session handler getter
+// ---------------------------------------------------------------------------
+//
+MNcdSessionHandler& CNcdProtocol::SessionHandlerL(
+ const MCatalogsContext& aContext ) const
+ {
+ TInt index = FindContextData( aContext );
+ if ( index == KErrNotFound )
+ {
+ User::Leave( KErrNotFound );
+ }
+ return iContexts[index]->SessionHandler();
+ }
+
+
+// ---------------------------------------------------------------------------
+// Protocol options setter
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::SetProtocolOptions( TUint32 aOptions )
+ {
+ DLTRACEIN(("aOptions: %d", aOptions ));
+ iProtocolOptions = aOptions;
+ }
+
+// ---------------------------------------------------------------------------
+// Add client-info to the request configuration
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::AddClientInfoToRequestL(
+ const MCatalogsContext& aContext,
+ CNcdRequestConfigurationData& aConfig )
+ {
+ DLTRACEIN((""));
+
+ // Connect to telephony services so it won't have to be done in each
+ // deviceinteraction method that require such services
+ iDeviceService->ConnectL();
+
+ CNcdKeyValueMap *userConfig = NULL;
+ // Search for the user configuration
+ TRAPD( err,
+ userConfig = &iConfigurationManager.ConfigurationsL( aContext,
+ MNcdUserConfiguration::ENcdConfigurationClientInfo ) );
+ if ( err != KErrNone )
+ {
+ // @ Error handling!
+ }
+
+ RPointerArray<CNcdKeyValuePair> configPairs;
+
+ // Using close since configPairs won't own the data it points to
+ CleanupClosePushL( configPairs );
+ if ( userConfig )
+ {
+ configPairs.ReserveL( userConfig->Pairs().Count() );
+
+ for ( TInt i = 0; i < userConfig->Pairs().Count(); ++i )
+ {
+ configPairs.AppendL( userConfig->Pairs()[i] );
+ }
+ }
+
+ // Add network info to the request
+ SetNetworkInfoL( aConfig );
+
+ CNcdRequestConfigurationClient* client =
+ CNcdRequestConfigurationClient::NewLC();
+
+ // Add hardware configuration info to the request
+ SetHardwareConfigurationL( client->Hardware(), configPairs );
+
+ // Add software configuration info to the request
+ AddSoftwareConfigurationL( aContext, *client, configPairs );
+
+
+ DLTRACE(("Add client-info to request"));
+ aConfig.AddClientL( client );
+ CleanupStack::Pop( client );
+
+ CleanupStack::PopAndDestroy( &configPairs );
+
+ // Close telephony services
+ User::LeaveIfError( iDeviceService->Close() );
+ }
+
+
+// ---------------------------------------------------------------------------
+// AddEngineClientInfoToRequestL
+// Adds a client info element describing the engine
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::AddEngineClientInfoToRequestL(
+ CNcdRequestConfigurationData& aConfig )
+ {
+ DLTRACEIN((""));
+
+ // Create a new client-element
+ CNcdRequestConfigurationClient* client =
+ CNcdRequestConfigurationClient::NewLC();
+
+ // Create a new software element
+ CNcdRequestConfigurationSoftware* software =
+ CNcdRequestConfigurationSoftware::NewLC();
+
+
+ // Set type, version and UID
+ software->SetSoftwareTypeL(
+ CNcdProviderUtils::EngineConfig().EngineType() );
+
+ software->SetSoftwareVersionL(
+ CNcdProviderUtils::EngineConfig().EngineVersion() );
+
+ software->SetSoftwareIdsL(
+ CNcdProviderUtils::EngineConfig().EngineUid(),
+ KNullDesC,
+ KNullDesC8 );
+
+
+ //Set provisioning for the engine
+ if ( CNcdProviderUtils::EngineConfig().EngineProvisioning().Length() )
+ {
+ CNcdConfigurationProtocolDetailImpl* detail =
+ CreateDetailLC( NcdConfigurationKeys::KProvisioning,
+ CNcdProviderUtils::EngineConfig().EngineProvisioning() );
+ software->AddSoftwareDetailsL( detail );
+ CleanupStack::Pop( detail );
+ }
+
+ // engine install drive
+ CNcdConfigurationProtocolDetailImpl* drive =
+ CreateDetailLC( NcdConfigurationKeys::KInstallDrive,
+ CNcdProviderUtils::EngineConfig().EngineInstallDrive() );
+ software->AddSoftwareDetailsL( drive );
+ CleanupStack::Pop( drive );
+
+
+ client->AddSoftwareL( software );
+ CleanupStack::Pop( software );
+
+ aConfig.AddClientL( client );
+ CleanupStack::Pop( client );
+
+ }
+
+// ---------------------------------------------------------------------------
+// SetNetworkInfoL
+// Fills the network information
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::SetNetworkInfoL( CNcdRequestConfigurationData& aConfig )
+ {
+ DLTRACEIN(( "" ));
+ {
+ DLTRACE(( "Setting MCC & MNC" ));
+ // Get & set current MCC and MNC
+ aConfig.SetNetworkMccL( iHomeMcc, iDeviceService->CurrentMccL() );
+ aConfig.SetNetworkMncL( iHomeMnc, iDeviceService->CurrentMncL() );
+ }
+
+ // Set service provider name
+ {
+ DLTRACE(( "Setting service provider name" ));
+ TBuf<MNcdDeviceService::KServiceProviderMaxLength> spName;
+ iDeviceService->ServiceProviderL( spName );
+ DLINFO(( _L("SP: %S"), &spName ));
+ aConfig.SetNetworkProviderL( spName );
+ }
+
+ // IMSI not set on purpose
+
+
+ // Set SMS center number
+ HBufC* smsc = iSmsUtils->SmsCenterNumberLC();
+ aConfig.SetNetworkSmscL( *smsc );
+ CleanupStack::PopAndDestroy( smsc );
+
+ /**
+ * @ Add: gid1/2, msisdn, operatorname
+ */
+
+
+ DLTRACEOUT(( "" ));
+ }
+
+
+// ---------------------------------------------------------------------------
+// AddSoftwareConfigurationL
+// Fills the client software information
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::AddSoftwareConfigurationL( const MCatalogsContext& aContext,
+ CNcdRequestConfigurationClient& aClient,
+ RPointerArray<CNcdKeyValuePair>& aConfigPairs )
+ {
+ DLTRACEIN((""));
+
+/*
+
+ RArray<TString> testmodes;
+
+ RArray<TNcdRequestCustomDetails> details;
+ KInstallDrive
+
+Done:
+ TString uid;
+ // Quasi-unique client id.
+ TString id;
+
+ //SIM-sensitive client id obtained by hashing the client id and IMSI code.
+ TString sid;
+ TString language;
+ TString type;
+ TString version;
+ RArray<TString> capabilities;
+
+*/
+
+ DLTRACE(("Hashing client ID with IMSI"));
+ const TDesC& clientId( iConfigurationManager.ClientIdL( aContext ) );
+
+ DLTRACE(("Getting SSID"));
+ TPtrC8 ssidPtr( iConfigurationManager.SsidL( aContext ) );
+ DLTRACE(( "SSID: %S, length: %d", &ssidPtr, ssidPtr.Length() ));
+
+ // Generate the SSID if it doesn't already exist
+/*
+ if ( !ssidPtr.Length() )
+ {
+ DLTRACE(("Creating a new SSID"));
+ HBufC8* ssid = NULL;
+ //ssid = HashImsiAndIdLC( clientId );
+ ssid = HashImsiLC();
+
+ DLTRACE(("Setting uid, client id and hash to request"));
+
+ // Ownership is transferred to the manager
+ iConfigurationManager.SetSsidL( aContext, ssid );
+
+ CleanupStack::Pop( ssid );
+ ssidPtr.Set( *ssid );
+
+ DLTRACE(( "Hashed SSID: %S", &ssidPtr ));
+
+ }
+*/
+
+ CNcdRequestConfigurationSoftware* software =
+ CNcdRequestConfigurationSoftware::NewLC();
+
+ // Use secureId as the client UID
+ software->SetSoftwareIdsL( CleanUidName( aContext.SecureId() ),
+ clientId, ssidPtr );
+
+ DLTRACE(( _L("Client ID: %S"), &clientId ));
+
+
+ // Add client & engine capabilities (must be done before
+ // AddConfigurationsToSoftwareDetailsL)
+ AddCapabilitiesL( *software, aConfigPairs );
+
+
+ if ( FindKey( NcdConfigurationKeys::KSoftwareType(), aConfigPairs )
+ != KErrNotFound )
+ {
+ DLTRACE(("Front-end overrides type"));
+ // Add software type
+ AddSoftwareUserConfigurationL( *software,
+ &CNcdRequestConfigurationSoftware::SetSoftwareTypeL, aConfigPairs,
+ NcdConfigurationKeys::KSoftwareType() );
+ }
+ else
+ {
+ DLTRACE(("Using type from engine"));
+ software->SetSoftwareTypeL(
+ CNcdProviderUtils::EngineConfig().EngineType() );
+ }
+
+
+ // Add software language
+ AddSoftwareUserConfigurationL( *software,
+ &CNcdRequestConfigurationSoftware::SetSoftwareLanguageL, aConfigPairs,
+ NcdConfigurationKeys::KSoftwareLanguage() );
+
+
+#ifdef CATALOGS_OVERRIDE_LANGUAGE
+ DLINFO(("Overriding software language"));
+ software->SetSoftwareLanguageL( KCatalogsOverrideSoftwareLanguage() );
+#endif
+
+ // Add software version
+ AddSoftwareUserConfigurationL( *software,
+ &CNcdRequestConfigurationSoftware::SetSoftwareVersionL, aConfigPairs,
+ NcdConfigurationKeys::KSoftwareVersion() );
+
+
+ // Add unused configurations as details
+ // Note: This MUST be done only after all AddUserConfigurationL calls
+ AddConfigurationsToSoftwareDetailsL( *software, aConfigPairs );
+
+ aClient.AddSoftwareL( software );
+ CleanupStack::Pop( software );
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// SetHardwareConfigurationL
+// Fills the client hardware information
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::SetHardwareConfigurationL(
+ CNcdRequestConfigurationHardware& aConfig,
+ RPointerArray<CNcdKeyValuePair>& aConfigPairs )
+ {
+ DLTRACEIN((""));
+/*
+ TString uaProfileUri;
+
+ TString manufacturer;
+ TString model;
+ RArray<TNcdConfigurationDisplay> displays;
+ RArray<TNcdRequestCustomDetails> details;
+ KFreeStorage
+
+Done:
+ //TString identification;
+ //TString language;
+ //TString platform;
+ //TString firmwareVersion;
+
+*/
+ // Set device identification
+ aConfig.SetHardwareIdentificationL(
+ *iDeviceService->DeviceIdentificationLC() );
+ CleanupStack::PopAndDestroy();
+
+ // Set device language
+ aConfig.SetHardwareLanguageL( *iDeviceService->DeviceLanguageLC() );
+ CleanupStack::PopAndDestroy(); // Device language
+
+ // Set platform
+ aConfig.SetHardwarePlatformL( KPlatformInfo );
+
+ // Set firmware
+ aConfig.SetHardwareFirmwareL( iDeviceService->FirmwareL() );
+
+ // Set device model and manufacturer
+ aConfig.SetHardwareModelL( iDeviceService->DeviceModelL() );
+ aConfig.SetHardwareManufacturerL( iDeviceService->DeviceManufacturerL() );
+
+ // Get free space for the temp drive used for downloads
+ TInt64 freeSpace = FreeDiskSpaceL( CNcdProviderUtils::FileSession(),
+ CNcdProviderUtils::EngineConfig().EngineTempDrive() );
+
+ // Format the integer and add to hardware details
+ RBuf formatBuffer;
+ CleanupClosePushL( formatBuffer );
+ formatBuffer.CreateL( 128 );
+ _LIT( KInt64, "%li" );
+
+ formatBuffer.Format( KInt64, freeSpace );
+ DLTRACE(("Adding free space to hardware details"));
+ CNcdConfigurationProtocolDetailImpl* freeSpaceDetail = CreateDetailLC(
+ NcdInternalConfigurationKeys::KFreeStorage(), formatBuffer );
+ aConfig.AddHardwareDetailsL( freeSpaceDetail );
+ CleanupStack::Pop( freeSpaceDetail );
+ CleanupStack::PopAndDestroy( &formatBuffer );
+
+ // Add flash-player details
+ DLTRACE(("Adding flash-player to hardware details"));
+ TUid flashUid;
+ TCatalogsVersion flashVersion;
+ TBool flashInstalled = FlashPlayerDataL( flashUid, flashVersion );
+ if ( flashInstalled )
+ {
+ CNcdConfigurationProtocolDetailImpl* flashPlayerDetail = CreateDetailLC(
+ NcdInternalConfigurationKeys::KFlashPlayer(), KNullDesC() );
+ CNcdConfigurationProtocolContentImpl* fpVersion =
+ CNcdConfigurationProtocolContentImpl::NewLC();
+ NcdProtocolUtils::AssignDesL(
+ fpVersion->iKey, KFlashPlayerVersion );
+ NcdProtocolUtils::AssignDesL(
+ fpVersion->iValue, *TCatalogsVersion::ConvertLC( flashVersion ) );
+ CleanupStack::PopAndDestroy();
+ flashPlayerDetail->iContents.AppendL( fpVersion );
+ CleanupStack::Pop( fpVersion );
+
+ CNcdConfigurationProtocolContentImpl* fpUid =
+ CNcdConfigurationProtocolContentImpl::NewLC();
+ NcdProtocolUtils::AssignDesL( fpUid->iKey, KFlashPlayerUid );
+ TUidName fpUidName = CleanUidName( flashUid );
+ NcdProtocolUtils::AssignDesL( fpUid->iValue, fpUidName );
+ flashPlayerDetail->iContents.AppendL( fpUid );
+ CleanupStack::Pop( fpUid );
+
+ aConfig.AddHardwareDetailsL( flashPlayerDetail );
+ CleanupStack::Pop( flashPlayerDetail );
+ }
+
+ // Add IMEI if necessary
+ if ( iProtocolOptions & ESendImei )
+ {
+ const TDesC& imei = iDeviceService->ImeiL();
+ DLINFO(( _L("Adding IMEI: %S"), &imei ));
+ CNcdConfigurationProtocolDetailImpl* imeiDetail =
+ CreateDetailLC( NcdInternalConfigurationKeys::KImei(), imei );
+ aConfig.AddHardwareDetailsL( imeiDetail );
+ CleanupStack::Pop( imeiDetail );
+ }
+
+ // Add all displays
+ while ( AddDisplayDetailsL( aConfig, aConfigPairs ) == KErrNone )
+ {
+ // Empty on purpose
+ }
+
+ AddProductCodeToHardwareDetailsL( aConfig, aConfigPairs );
+ AddFirmwareDetailsToHardwareDetailsL( aConfig );
+ DLTRACEOUT((""));
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// Adds a configuration from the user to the request configuration
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::AddConfigurationsToSoftwareDetailsL(
+ CNcdRequestConfigurationSoftware& aConfig,
+ RPointerArray<CNcdKeyValuePair>& aUserConfig ) const
+ {
+ DLTRACEIN(("Config count: %d", aUserConfig.Count() ));
+
+ // All leftover key-value -pairs are added as details
+ for ( TInt i = 0; i < aUserConfig.Count(); ++i )
+ {
+ CNcdConfigurationProtocolDetailImpl* detail =
+ CreateDetailLC( aUserConfig[i]->Key(), aUserConfig[i]->Value() );
+ aConfig.AddSoftwareDetailsL( detail );
+ CleanupStack::Pop( detail );
+ }
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Creates a detail object
+// ---------------------------------------------------------------------------
+//
+CNcdConfigurationProtocolDetailImpl* CNcdProtocol::CreateDetailLC(
+ const TDesC& aKey, const TDesC& aValue ) const
+ {
+ CNcdConfigurationProtocolDetailImpl* details =
+ CNcdConfigurationProtocolDetailImpl::NewLC();
+
+ delete details->iId;
+ details->iId = NULL;
+ details->iId = aKey.AllocL();
+
+ delete details->iValue;
+ details->iValue = NULL;
+ details->iValue = aValue.AllocL();
+ return details;
+ }
+
+// ---------------------------------------------------------------------------
+// Adds a configuration from the user to the request configuration
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::AddSoftwareUserConfigurationL(
+ CNcdRequestConfigurationSoftware& aConfig,
+ void (CNcdRequestConfigurationSoftware::*aValueSetter)( const TDesC& ),
+ RPointerArray<CNcdKeyValuePair>& aUserConfig,
+ const TDesC& aKey ) const
+ {
+ DLTRACEIN(( _L("Count: %d, Key: %S"), aUserConfig.Count(), &aKey ));
+ DASSERT( aValueSetter );
+
+ TInt index = FindKey( aKey, aUserConfig );
+ if ( index != KErrNotFound )
+ {
+ DLTRACE(( _L("Calling the setter with value: %S"),
+ &aUserConfig[index]->Value() ));
+
+ const TDesC& value = aUserConfig[index]->Value();
+ (aConfig.*aValueSetter )( value );
+
+ aUserConfig.Remove( index );
+ }
+
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Adds client capabilities to the request
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::AddCapabilitiesL(
+ CNcdRequestConfigurationSoftware& aConfig,
+ RPointerArray<CNcdKeyValuePair>& aUserConfig ) const
+ {
+ DLTRACEIN((""));
+ TInt i = aUserConfig.Count() - 1;
+ while( i >= 0 )
+ {
+ // Check if the configuration is actually a capability
+ if ( aUserConfig[i]->Key().Compare(
+ NcdConfigurationKeys::KCapability ) == 0 )
+ {
+ // Checks that the capability is supported by the engine
+ if ( IsCapabilitySupported( aUserConfig[i]->Value() ) )
+ {
+ DLTRACE(( _L("Adding capability: %S"), &aUserConfig[i]->Value() ));
+ aConfig.AddSoftwareCapabilityL( aUserConfig[i]->Value() );
+ }
+
+ // Just remove since the pairs are not owned by the array
+ aUserConfig.Remove( i );
+ }
+ --i;
+ }
+
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Checks if the engine supports the given capability or not
+// ---------------------------------------------------------------------------
+//
+TBool CNcdProtocol::IsCapabilitySupported( const TDesC& aCapability ) const
+ {
+ /**
+ * @ Update engine/provider's capabilities here
+ */
+ DLTRACEIN((""));
+ /**
+ * Check that engine supports the capability
+ */
+ if ( NcdCapabilities::KSearch().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+ else if ( NcdCapabilities::KSubscriptions().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+/*
+ else if ( NcdCapabilities::KEmbeddedSessions().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+*/
+/*
+ else if ( NcdCapabilities::KActivities().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+*/
+/*
+ else if ( NcdCapabilities::KLegacySubscriptions().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+*/
+/*
+ else if ( NcdCapabilities::KUpload().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+*/
+/*
+ else if ( NcdCapabilities::KReDownload().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+*/
+/*
+ else if ( NcdCapabilities::KGpsLocation().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+*/
+/*
+ else if ( NcdCapabilities::KDelayedTransfer().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+*/
+/*
+ else if ( NcdCapabilities::KAutoDownload().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+*/
+/*
+ else if ( NcdCapabilities::KXmlResponseFiltering().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+*/
+ else if ( NcdCapabilities::KInstallationReport().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+/*
+ else if ( NcdCapabilities::KBrowseFiltering().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+
+ else if ( NcdCapabilities::KClientReview().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+
+ else if ( NcdCapabilities::KPromotionalEntities().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+*/
+ else if ( NcdCapabilities::KDirectSchemeLinks().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+ else if ( NcdCapabilities::KIndirectSchemeLinks().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+/*
+ else if ( NcdCapabilities::KEntityRequest().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+
+ else if ( NcdCapabilities::KDiffQuery().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+ else if ( NcdCapabilities::KUpLevel().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+ else if ( NcdCapabilities::KRemoteContent().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+ else if ( NcdCapabilities::KPredefinedSearch().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+ else if ( NcdCapabilities::KPredefinedPurchase().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+*/
+ else if ( NcdCapabilities::KCacheExpiration().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+/*
+ else if ( NcdCapabilities::KMultiPurchase().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+*/
+ else if ( NcdCapabilities::KMultiDownload().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+ else if ( NcdCapabilities::KBasicQueries().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+ else if ( NcdCapabilities::KSourceScopeCookies().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+ else if ( NcdCapabilities::KSimScopeCookies().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+/*
+ else if ( NcdCapabilities::KCancelPurchase().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+
+ else if ( NcdCapabilities::KSmsAction().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+*/
+ else if ( NcdCapabilities::KDrmClientDownload().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+/*
+ else if ( NcdCapabilities::KGiftPurchase().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+*/
+ else if ( NcdCapabilities::KUniversalSubscriptions().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+ else if ( NcdCapabilities::KDownloadReport().Compare( aCapability ) == 0 )
+ {
+ return ETrue;
+ }
+
+ DLTRACEOUT((""));
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// AddCookiesL
+// ---------------------------------------------------------------------------
+//
+TBool CNcdProtocol::AddCookiesL( const MCatalogsContext& aContext,
+ RPointerArray<MNcdConfigurationProtocolCookie>& aCookies,
+ const TDesC& aServerUri,
+ const TDesC& aNamespace )
+ {
+ DLTRACEIN((""));
+
+ TBool removedCookies = EFalse;
+
+ TInt index = FindContextData( aContext );
+ if ( index != KErrNotFound )
+ {
+
+ // Get SSID
+ const TDesC8& ssid( iConfigurationManager.SsidL( aContext ) );
+
+
+ // Get server details
+ MNcdServerDetails& details(
+ iConfigurationManager.ServerDetailsL( aContext,
+ aServerUri,
+ aNamespace ));
+
+ // Remove expired cookies
+ removedCookies = details.RemoveExpiredCookies();
+
+ // If the cookie's scope is "sim" it has to match the given SSID
+ RPointerArray<const MNcdConfigurationProtocolCookie> cookies(
+ details.CookiesL( ssid ) );
+
+ CleanupClosePushL( cookies );
+
+ TIdentityRelation<MNcdConfigurationProtocolCookie> identity(
+ CNcdConfigurationProtocolCookie::Identity );
+
+ DLTRACE(( "Adding %i cookies to the request", cookies.Count() ));
+ for ( TInt i = 0; i < cookies.Count(); ++i )
+ {
+
+ // Only add "saveAndSend" cookies
+ if ( cookies[i]->Type().Compare(
+ NcdConfigurationProtocolCookieTypes::KSaveAndSend ) == 0 )
+ {
+ DLTRACE(( _L("Adding cookie with key: %S"), &cookies[i]->Key() ));
+ CNcdConfigurationProtocolCookie* copy =
+ CNcdConfigurationProtocolCookie::NewLC( *cookies[i] );
+
+
+ // Ensure that a matching cookie doesn't already exist
+ TInt oldCookie = aCookies.Find( copy, identity );
+ if ( oldCookie != KErrNotFound )
+ {
+ delete aCookies[oldCookie];
+ aCookies[oldCookie] = copy;
+ }
+ else
+ {
+ // Add cookie to request, ownership is transferred
+ aCookies.AppendL( copy );
+ }
+
+ CleanupStack::Pop( copy );
+ }
+ }
+ DLTRACE(( "Cookies added" ));
+ CleanupStack::PopAndDestroy( &cookies );
+
+ }
+ DLTRACEOUT((""));
+ return removedCookies;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Add cookies to the request
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::AddCookiesToRequestL(
+ CNcdRequestBase& aRequest,
+ RPointerArray<MNcdConfigurationProtocolCookie>& aCookies )
+ {
+ for ( TInt i = 0; i < aCookies.Count(); ++i )
+ {
+ aRequest.AddCookieL( aCookies[i] );
+ aCookies[i] = NULL;
+ }
+ aCookies.Reset();
+ }
+
+
+// ---------------------------------------------------------------------------
+// Add cookies to the config request
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::AddCookiesToConfigRequestL(
+ CNcdRequestConfigurationData& aConfig,
+ RPointerArray<MNcdConfigurationProtocolCookie>& aCookies )
+ {
+ for ( TInt i = 0; i < aCookies.Count(); ++i )
+ {
+ aConfig.AddCookieL( aCookies[i] );
+ aCookies[i] = NULL;
+ }
+ aCookies.Reset();
+ }
+
+
+// ---------------------------------------------------------------------------
+// Searches for the given key in the array
+// ---------------------------------------------------------------------------
+//
+TInt CNcdProtocol::FindKey( const TDesC& aKey,
+ const RPointerArray<CNcdKeyValuePair>& aArray ) const
+ {
+ for ( TInt i = 0; i < aArray.Count(); ++i )
+ {
+ if ( aArray[i]->Key().Compare( aKey ) == 0 )
+ {
+ return i;
+ }
+ }
+ return KErrNotFound;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Reads the value of the given key as TInt and removes the key
+// ---------------------------------------------------------------------------
+//
+TInt CNcdProtocol::AddDisplayDetailsL(
+ CNcdRequestConfigurationHardware& aConfig,
+ RPointerArray<CNcdKeyValuePair>& aConfigPairs )
+ {
+ DLTRACEIN((""));
+ TInt index = FindKey( NcdConfigurationKeys::KDisplay, aConfigPairs );
+ if ( index != KErrNotFound )
+ {
+ DLTRACE(("Found the key"));
+ TInt disp = 0;
+ TInt width = 0;
+ TInt height = 0;
+ TInt colors = 0;
+
+ // Interpret the value as TInts
+ TInt err = InterpretDisplayValue( aConfigPairs[index]->Value(),
+ disp, width, height, colors );
+
+ // Remove the pair (doesn't matter whether the conversion was
+ // successful or not
+ aConfigPairs.Remove( index );
+ if ( err == KErrNone )
+ {
+ DLTRACE(("Adding display details to the config"));
+ aConfig.AddHardwareDisplayL( colors, height, width );
+ }
+ return err;
+ }
+ return KErrNotFound;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Interprets a display value
+// ---------------------------------------------------------------------------
+//
+TInt CNcdProtocol::InterpretDisplayValue(
+ const TDesC& aValue, TInt& aDispNumber, TInt& aWidth,
+ TInt& aHeight, TInt& aColors ) const
+ {
+ DLTRACEIN((""));
+ TLex lex( aValue );
+
+ TInt err = lex.Val( aDispNumber );
+ if ( err == KErrNone )
+ {
+ lex.SkipSpaceAndMark();
+ err = lex.Val( aWidth );
+ if ( err == KErrNone )
+ {
+ lex.SkipSpaceAndMark();
+ err = lex.Val( aHeight );
+ if ( err == KErrNone )
+ {
+ lex.SkipSpaceAndMark();
+ lex.Val( aColors );
+ }
+ }
+ }
+
+ DLTRACEOUT(("disp: %d, width: %d, height: %d, colors: %d",
+ aDispNumber, aWidth, aHeight, aColors ));
+ return err;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Reads the value of the given key and and removes the config pair
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::AddProductCodeToHardwareDetailsL(
+ CNcdRequestConfigurationHardware& aConfig,
+ RPointerArray<CNcdKeyValuePair>& aConfigPairs )
+ {
+ DLTRACEIN((""));
+
+ // First try to get the product code from the device service.
+ // If device service gives the product code, then always use it.
+ // If device service does not give the product code, then check
+ // if product code is given through the NCD API and use it if
+ // available.
+
+ // Get possible product code from the device service.
+ HBufC* productCode( iDeviceService->ProductCodeLC() );
+
+ // Get the index value for the possible product code in
+ // config pair array.
+ TInt index(
+ FindKey( NcdConfigurationKeys::KDeviceProductCode,
+ aConfigPairs ) );
+
+ // Check if the config pair array contains the product code.
+ if ( index != KErrNotFound )
+ {
+ DLINFO(("Product code given in config pair."));
+ if ( !productCode )
+ {
+ DLINFO(("Use config pair product code"));
+
+ // Product code was not gotten from device service.
+ // So, use the config pair value.
+ productCode = aConfigPairs[ index ]->Value().AllocLC();
+ }
+
+ // Remove the pair is required. This way the config pair will not
+ // be included into the software details element in the server requests.
+ aConfigPairs.Remove( index );
+ }
+
+ // Check if product code was gotten from device service or from
+ // the config pair.
+ if ( productCode )
+ {
+ DLINFO(( _L("Adding productCode: %S"), productCode ));
+
+ // Add the hardware detail because value exists.
+ CNcdConfigurationProtocolDetailImpl* productCodeDetail(
+ CreateDetailLC( NcdConfigurationKeys::KDeviceProductCode(),
+ *productCode ) );
+ aConfig.AddHardwareDetailsL( productCodeDetail );
+ CleanupStack::Pop( productCodeDetail );
+
+ CleanupStack::PopAndDestroy( productCode );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// Creates a new context data object or returns an existing one
+// ---------------------------------------------------------------------------
+//
+CNcdProtocol::CContextData& CNcdProtocol::CreateContextDataL(
+ const MCatalogsContext& aContext )
+ {
+ DLTRACEIN((""));
+ TInt index = FindContextData( aContext );
+ if ( index == KErrNotFound )
+ {
+ // Create a new session handler
+ CNcdSessionHandler* sessionHandler = CNcdSessionHandler::NewL();
+
+ CleanupStack::PushL( sessionHandler );
+
+
+ // Create a new context data
+ // owns session and cookie handlers
+ CContextData* newData = new( ELeave ) CContextData( aContext,
+ sessionHandler );
+
+ CleanupStack::Pop( sessionHandler );
+ CleanupStack::PushL( newData );
+
+ iContexts.AppendL( newData );
+ CleanupStack::Pop( newData );
+ index = iContexts.Count() - 1;
+ }
+ DLTRACEOUT(( "index: %d", index ));
+ return *iContexts[index];
+ }
+
+
+// ---------------------------------------------------------------------------
+// Searches for the given context in contexts
+// ---------------------------------------------------------------------------
+//
+TInt CNcdProtocol::FindContextData( const MCatalogsContext& aContext ) const
+ {
+ TIdentityRelation<CContextData> match( CNcdProtocol::MatchContextDatas );
+ CContextData data( aContext, NULL );
+
+ return iContexts.Find( &data, match );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Compares two contexts
+// ---------------------------------------------------------------------------
+//
+TBool CNcdProtocol::MatchContextDatas( const CContextData& aFirst,
+ const CContextData& aSecond )
+ {
+ return aFirst.FamilyId() == aSecond.FamilyId();
+ }
+
+
+// ---------------------------------------------------------------------------
+// Gets flash player data
+// ---------------------------------------------------------------------------
+//
+TBool CNcdProtocol::FlashPlayerDataL( TUid& aUid, TCatalogsVersion& aVersion )
+ {
+ DLTRACEIN((""));
+
+ TUid flashUid = iDeviceService->FlashPlayerUidL();
+
+ if( flashUid.iUid == NULL )
+ {
+ return EFalse;
+ }
+
+ TCatalogsVersion flashVersion;
+ MNcdInstallationService& installationService =
+ CNcdProviderUtils::InstallationServiceL();
+ TInt err = installationService.ApplicationVersion( flashUid, flashVersion );
+
+ if ( err != KErrNone )
+ {
+ DLTRACEOUT(("Error occured while retrieving flash player version"))
+ return EFalse;
+ }
+
+ aUid = flashUid;
+ aVersion = flashVersion;
+
+ DLTRACEOUT(("Flash player uid: %d, version: %d.%d.%d",
+ aUid.iUid,
+ aVersion.iMajor,
+ aVersion.iMinor,
+ aVersion.iBuild));
+ return ETrue;
+ }
+
+// ---------------------------------------------------------------------------
+// Add additional firmware information
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::AddFirmwareDetailsToHardwareDetailsL(
+ CNcdRequestConfigurationHardware& aConfig )
+ {
+ DLTRACEIN((""));
+ RBuf buf;
+ buf.CreateL( MNcdDeviceService::KFirmwareDetailMaxLength );
+ CleanupClosePushL( buf );
+
+ RFs& fs = CNcdProviderUtils::FileSession();
+
+ iDeviceService->GetProductType( buf, fs );
+ AddHardwareDetailL( aConfig, KProductType, buf );
+ buf.Zero();
+
+ iDeviceService->GetFirmwareId( buf, fs );
+ AddHardwareDetailL( aConfig, KFirmwareId, buf );
+ buf.Zero();
+
+ iDeviceService->GetFirmwareVersion1( buf );
+ AddHardwareDetailL( aConfig, KFirmwareVersion1, buf );
+ buf.Zero();
+
+ iDeviceService->GetFirmwareVersion2( buf );
+ AddHardwareDetailL( aConfig, KFirmwareVersion2, buf );
+ buf.Zero();
+
+ iDeviceService->GetFirmwareVersion3( buf, fs );
+ AddHardwareDetailL( aConfig, KFirmwareVersion3, buf );
+ buf.Zero();
+
+ AddHardwareDetailL( aConfig, KSimLockStatus, KFalseAsZero );
+
+ CleanupStack::PopAndDestroy( &buf );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Helper method for adding a detail to hardware details
+// ---------------------------------------------------------------------------
+//
+void CNcdProtocol::AddHardwareDetailL(
+ CNcdRequestConfigurationHardware& aConfig,
+ const TDesC& aKey,
+ const TDesC& aValue )
+ {
+ if ( aValue.Length() )
+ {
+ CNcdConfigurationProtocolDetailImpl* detail(
+ CreateDetailLC( aKey,
+ aValue ) );
+ aConfig.AddHardwareDetailsL( detail );
+ CleanupStack::Pop( detail );
+ }
+ }