diff -r fcbbe021d614 -r 9c97ad6591ae cmmanager/cmmgr/cmmserver/src/cmmdestinationinstance.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmmanager/cmmgr/cmmserver/src/cmmdestinationinstance.cpp Mon May 03 12:53:07 2010 +0300 @@ -0,0 +1,1683 @@ +/* +* Copyright (c) 2009-2010 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: +* Session side object representing a destination. +* +*/ + + +#include +#include +#include + +#include "cmmdestinationinstance.h" +#include "cmmsession.h" +#include "cmmcache.h" +#include "cmmconnmethodinstance.h" +#include "cmmconnmethoditem.h" +#include "cmmanagertextresolver.h" + +#include "OstTraceDefinitions.h" +#ifdef OST_TRACE_COMPILER_IN_USE +#include "cmmdestinationinstanceTraces.h" +#endif + + +// --------------------------------------------------------------------------- +// Two phased construction. +// --------------------------------------------------------------------------- +// +CCmmDestinationInstance* CCmmDestinationInstance::NewL( CCmmSession* aCmmSession, CCmmCache* aCache ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_NEWL_ENTRY ); + + CCmmDestinationInstance* self = CCmmDestinationInstance::NewLC( aCmmSession, aCache ); + CleanupStack::Pop( self ); + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_NEWL_EXIT ); + return self; + } + +// --------------------------------------------------------------------------- +// Two phased construction. +// --------------------------------------------------------------------------- +// +CCmmDestinationInstance* CCmmDestinationInstance::NewLC( CCmmSession* aCmmSession, CCmmCache* aCache ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_NEWLC_ENTRY ); + + CCmmDestinationInstance* self = new( ELeave ) CCmmDestinationInstance( aCmmSession, aCache ); + CleanupClosePushL( *self ); + self->ConstructL(); + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_NEWLC_EXIT ); + return self; + } + +// --------------------------------------------------------------------------- +// Destructor. +// --------------------------------------------------------------------------- +// +CCmmDestinationInstance::~CCmmDestinationInstance() + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_CCMMDESTINATIONINSTANCE_ENTRY ); + + // Tell cache this handle is beeing closed. Cache will update it's own + // bookkeeping accordingly. + if ( iCache ) + { + iCache->CloseDestination( *this ); + } + delete iNetworkRecord; + delete iDestApRecord; + delete iMetadataRecord; + + iConnMethodItemArray.Close(); + iConnMethodsToBeDeleted.Close(); + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_CCMMDESTINATIONINSTANCE_EXIT ); + } + +// --------------------------------------------------------------------------- +// Constructor. +// --------------------------------------------------------------------------- +// +CCmmDestinationInstance::CCmmDestinationInstance( + CCmmSession* aCmmSession, + CCmmCache* aCache ) + : + iCmmSession( aCmmSession ), + iCache( aCache ) + { + OstTraceFunctionEntry0( DUP1_CCMMDESTINATIONINSTANCE_CCMMDESTINATIONINSTANCE_ENTRY ); + + iNetworkRecord = NULL; + iDestApRecord = NULL; + iMetadataRecord = NULL; + + iNetworkRecordStatus = ECmmRecordStatusBlank; + iDestApRecordStatus = ECmmRecordStatusBlank; + iMetadataRecordStatus = ECmmRecordStatusBlank; + + iStatus = ECmmDestinationStatusChanged; + iId = 0; + iHandle = 0; + + iProtectionChanged = EFalse; + iLastProtectionLevel = CMManager::EProtLevel0; + iCurrentProtectionLevel = CMManager::EProtLevel0; + + OstTraceFunctionExit0( DUP1_CCMMDESTINATIONINSTANCE_CCMMDESTINATIONINSTANCE_EXIT ); + } + +// --------------------------------------------------------------------------- +// Second phase constructor. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::ConstructL() + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_CONSTRUCTL_ENTRY ); + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_CONSTRUCTL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Set the destination ID. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::SetId( const TUint32& aId ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETID_ENTRY ); + + iId = aId; + + // If this is the real ID (not the temporary ID of a new unsaved destination), + // write it also into network record. + if ( aId > KCmmDestIdIntervalMin && aId < KCmmDestIdIntervalMax ) + { + iNetworkRecord->SetRecordId( aId - KCmDefaultDestinationAPTagId ); + iDestApRecord->iRecordTag = aId; + iDestApRecord->iCustomSelectionPolicy = ( aId - KCmDefaultDestinationAPTagId ); + iMetadataRecord->iSNAP = aId; + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETID_EXIT ); + } + +// --------------------------------------------------------------------------- +// Get the destination ID. +// --------------------------------------------------------------------------- +// +TUint32 CCmmDestinationInstance::GetId() const + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETID_ENTRY ); + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETID_EXIT ); + return iId; + } + +// --------------------------------------------------------------------------- +// Set the current status of this destination. +// ECmmDestinationStatusValid: Contents in sync with database. +// ECmmDestinationStatusChanged: Contents differ from database contents. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::SetStatus( const TCmmDestinationStatus& aStatus ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETSTATUS_ENTRY ); + + switch ( aStatus ) + { + // Fallthrough intended + case ECmmDestinationStatusValid: + case ECmmDestinationStatusChanged: + iStatus = aStatus; + break; + default: + ASSERT(0); // Error, invalid status. + break; + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETSTATUS_EXIT ); + } + +// --------------------------------------------------------------------------- +// Gets the current status of this destination instance. +// --------------------------------------------------------------------------- +// +TCmmDestinationStatus CCmmDestinationInstance::GetStatus() const + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETSTATUS_ENTRY ); + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETSTATUS_EXIT ); + return iStatus; + } + +// --------------------------------------------------------------------------- +// Get handle ID. +// --------------------------------------------------------------------------- +// +TInt CCmmDestinationInstance::GetHandle() const + { + return iHandle; + } + +// --------------------------------------------------------------------------- +// Set handle ID. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::SetHandle( const TInt& aHandle ) + { + iHandle = aHandle; + } + +// --------------------------------------------------------------------------- +// Set the record status for all records. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::SetStatusForAllRecords( const TCmmRecordStatus& aStatus ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETSTATUSFORALLRECORDS_ENTRY ); + + iDestApRecordStatus = aStatus; + iNetworkRecordStatus = aStatus; + iMetadataRecordStatus = aStatus; + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETSTATUSFORALLRECORDS_EXIT ); + } + +// --------------------------------------------------------------------------- +// Get the destination element ID. +// --------------------------------------------------------------------------- +// +TUint32 CCmmDestinationInstance::GetElementIdL() + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETELEMENTIDL_ENTRY ); + + RefreshRecordL( ECmmDestNetworkRecord ); + + if ( !iNetworkRecord ) + { + User::Leave( KErrCorrupt ); + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETELEMENTIDL_EXIT ); + return iNetworkRecord->ElementId() & KCDMaskShowField; + } + +// --------------------------------------------------------------------------- +// Get the destination access point record's record tag (destination ID). +// --------------------------------------------------------------------------- +// +TUint32 CCmmDestinationInstance::GetRecordTagFromApRecordL() + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETRECORDTAGFROMAPRECORDL_ENTRY ); + + RefreshRecordL( ECmmDestApRecord ); + + if ( !iDestApRecord ) + { + User::Leave( KErrCorrupt ); + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETRECORDTAGFROMAPRECORDL_EXIT ); + return iDestApRecord->iRecordTag; + } + +// --------------------------------------------------------------------------- +// Sets a record pointer to the one given as parameter, Ownership is +// transfered. Also deletes the previous pointer and sets the record status +// to 'ECmmRecordStatusLoaded'. +// --------------------------------------------------------------------------- +// +TInt CCmmDestinationInstance::SetRecordPointer( + const TCmmDbRecords& aDestRecord, + CommsDat::CCDRecordBase* aRecordPointer ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETRECORDPOINTER_ENTRY ); + + TInt ret( KErrNone ); + switch ( aDestRecord ) + { + case ECmmDestNetworkRecord: + { + delete iNetworkRecord; + iNetworkRecord = static_cast( aRecordPointer ); + iNetworkRecordStatus = ECmmRecordStatusLoaded; + } + break; + case ECmmDestApRecord: + { + delete iDestApRecord; + iDestApRecord = static_cast( aRecordPointer ); + iDestApRecordStatus = ECmmRecordStatusLoaded; + } + break; + case ECmmDestMetadataRecord: + { + delete iMetadataRecord; + iMetadataRecord = static_cast( aRecordPointer ); + iMetadataRecordStatus = ECmmRecordStatusLoaded; + } + break; + default: + { + ret = KErrNotFound; + } + break; + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETRECORDPOINTER_EXIT ); + return ret; + } + +// --------------------------------------------------------------------------- +// Gets a reference to the requested record pointer. +// --------------------------------------------------------------------------- +// +TInt CCmmDestinationInstance::GetRecordPointer( + const TCmmDbRecords& aDestRecord, + CommsDat::CCDRecordBase*& aRecordPointer ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETRECORDPOINTER_ENTRY ); + + TInt ret( KErrNone ); + aRecordPointer = NULL; + switch ( aDestRecord ) + { + case ECmmDestNetworkRecord: + { + aRecordPointer = static_cast( iNetworkRecord ); + } + break; + case ECmmDestApRecord: + { + aRecordPointer = static_cast( iDestApRecord ); + } + break; + case ECmmDestMetadataRecord: + { + aRecordPointer = static_cast( iMetadataRecord ); + } + break; + default: + { + ASSERT( 0 ); + ret = KErrNotFound; + } + break; + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETRECORDPOINTER_EXIT ); + return ret; + } + +// --------------------------------------------------------------------------- +// Save the contents of this destination into database. All connection methods +// including embedded destination, that the client has open handles to, are +// also updated. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::UpdateL() + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_UPDATEL_ENTRY ); + + if ( AllMandatoryRecordsContainData() ) + { + // Check for metadata conflicts. + if ( ConflictingMetadataFoundL() ) + { + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_UPDATEL_EXIT ); + + User::Leave( KErrAlreadyExists ); + } + + // Check that the destination name is still valid and not in use already. + if ( iCache->DestinationExistsWithNameL( iNetworkRecord->iRecordName.GetL(), iId ) ) + { + OstTraceFunctionExit0( DUP1_CCMMDESTINATIONINSTANCE_UPDATEL_EXIT ); + + User::Leave( KErrAlreadyExists ); + } + + iCache->UpdateDestinationL( *this ); + } + else + { + User::Leave( KErrCorrupt ); + } + + OstTraceFunctionExit0( DUP2_CCMMDESTINATIONINSTANCE_UPDATEL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Get the destination name. +// --------------------------------------------------------------------------- +// +TDesC& CCmmDestinationInstance::GetDestinationNameL() + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETDESTINATIONNAMEL_ENTRY ); + + RefreshRecordL( ECmmDestNetworkRecord ); + + if ( !iNetworkRecord ) + { + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETDESTINATIONNAMEL_EXIT ); + + User::Leave( KErrCorrupt ); + } + + OstTraceFunctionExit0( DUP1_CCMMDESTINATIONINSTANCE_GETDESTINATIONNAMEL_EXIT ); + return iNetworkRecord->iRecordName.GetL(); + } + +// --------------------------------------------------------------------------- +// Get the localised destination name. +// --------------------------------------------------------------------------- +// +HBufC* CCmmDestinationInstance::GetLocalisedDestinationNameL() + { + RefreshRecordL( ECmmDestNetworkRecord ); + + if ( !iNetworkRecord ) + { + User::Leave( KErrCorrupt ); + } + + TUint32 purpose( 0 ); + GetMetadataL( CMManager::ESnapMetadataPurpose, purpose ); + HBufC* resolvedText( NULL ); + TBool isLocalised( EFalse ); + switch ( purpose ) + { + case CMManager::ESnapPurposeInternet: + { + _LIT( KDestinationTextId, "txt_occ_dblist_internet"); + resolvedText = CCmManagerTextResolver::ResolveTextL( KDestinationTextId ); + isLocalised = ETrue; + } + break; + case CMManager::ESnapPurposeOperator: + { + _LIT( KDestinationTextId, "txt_occ_dblist_operator_services"); + resolvedText = CCmManagerTextResolver::ResolveTextL( KDestinationTextId ); + isLocalised = ETrue; + } + break; + case CMManager::ESnapPurposeIntranet: + { + _LIT( KDestinationTextId, "txt_occ_dblist_intranet"); + resolvedText = CCmManagerTextResolver::ResolveTextL( KDestinationTextId ); + isLocalised = ETrue; + } + break; + default: + break; + } + + // Not Internet, operator or intranet...or something went wrong + if ( !isLocalised || ( isLocalised && !resolvedText ) ) + { + resolvedText = ( iNetworkRecord->iRecordName.GetL() ).AllocL(); + } + + return resolvedText; + } + +// --------------------------------------------------------------------------- +// Set the destination name. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::SetDestinationNameL( const TDesC& aDestinationName ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETDESTINATIONNAMEL_ENTRY ); + + //TODO, capability check depending on destination protection level, or if it is internet destination. Internet destination should be protected always? + + // Write action, load all records. + LoadAllRecordsL(); + + iNetworkRecord->iRecordName.SetL( aDestinationName ); + iDestApRecord->iRecordName.SetL( aDestinationName ); + + iNetworkRecordStatus = ECmmRecordStatusModified; + iDestApRecordStatus = ECmmRecordStatusModified; + iStatus = ECmmDestinationStatusChanged; + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETDESTINATIONNAMEL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Get metadata of specified type. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::GetMetadataL( + const CMManager::TSnapMetadataField& aMetadataField, + TUint32& aMetadata ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETMETADATAL_ENTRY ); + + RefreshRecordL( ECmmDestMetadataRecord ); + + if ( !iMetadataRecord ) + { + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETMETADATAL_EXIT ); + + User::Leave( KErrCorrupt ); + } + + switch ( aMetadataField ) + { + case CMManager::ESnapMetadataInternet: + aMetadata = ( TUint32 )( iMetadataRecord->iMetadata ) & CMManager::ESnapMetadataInternet; + break; + case CMManager::ESnapMetadataHighlight: + aMetadata = ( TUint32 )( iMetadataRecord->iMetadata ) & CMManager::ESnapMetadataHighlight; + break; + case CMManager::ESnapMetadataHiddenAgent: + aMetadata = ( TUint32 )( iMetadataRecord->iMetadata ) & CMManager::ESnapMetadataHiddenAgent; + break; + case CMManager::ESnapMetadataDestinationIsLocalised: + aMetadata = ( ( TUint32 )( iMetadataRecord->iMetadata ) & CMManager::ESnapMetadataDestinationIsLocalised ) >> 4; + break; + case CMManager::ESnapMetadataPurpose: + aMetadata = ( ( TUint32 )( iMetadataRecord->iMetadata ) & CMManager::ESnapMetadataPurpose ) >> 8; + break; + default: + User::Leave( KErrArgument ); + break; + } + + OstTraceFunctionExit0( DUP1_CCMMDESTINATIONINSTANCE_GETMETADATAL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Set metadata of specified type. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::SetMetadataL( + const CMManager::TSnapMetadataField& aMetadataField, + const TUint32& aMetadata ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETMETADATAL_ENTRY ); + + // Write action, load all records. + LoadAllRecordsL(); + + switch ( aMetadataField ) + { + case CMManager::ESnapMetadataInternet: + SetMetadataInternetL( aMetadata ); + break; + case CMManager::ESnapMetadataHighlight: + SetMetadataHighlight( aMetadata ); + break; + case CMManager::ESnapMetadataHiddenAgent: + SetMetadataHiddenAgentL( aMetadata ); + break; + case CMManager::ESnapMetadataDestinationIsLocalised: + SetMetadataLocalizationL( aMetadata ); + break; + case CMManager::ESnapMetadataPurpose: + SetMetadataPurposeL( aMetadata ); + break; + default: + User::Leave( KErrArgument ); + break; + } + + iMetadataRecordStatus = ECmmRecordStatusModified; + iStatus = ECmmDestinationStatusChanged; + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETMETADATAL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Get destination protection level. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::GetProtectionL( CMManager::TProtectionLevel& aProtectionLevel ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETPROTECTIONL_ENTRY ); + + RefreshRecordL( ECmmDestMetadataRecord ); + + if ( !iMetadataRecord ) + { + User::Leave( KErrCorrupt ); + } + + TUint32 value = ( ( TUint32 )( iMetadataRecord->iMetadata ) & KDestProtectionLevelMask ) >> KBitsToShiftDestProtectionLevel; + switch ( value ) + { + case CMManager::EProtLevel0: + aProtectionLevel = CMManager::EProtLevel0; + break; + case CMManager::EProtLevel1: + aProtectionLevel = CMManager::EProtLevel1; + break; + case CMManager::EProtLevel2: + aProtectionLevel = CMManager::EProtLevel2; + break; + case CMManager::EProtLevel3: + aProtectionLevel = CMManager::EProtLevel3; + break; + default: + User::Leave( KErrCorrupt ); + break; + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETPROTECTIONL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Set destination protection level. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::SetProtectionL( + CMManager::TProtectionLevel aProtectionLevel ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETPROTECTIONL_ENTRY ); + + // Write action, load all records. + LoadAllRecordsL(); + + //TODO, verify capability check is done (NetworkControl). + + iCurrentProtectionLevel = aProtectionLevel; + if ( !iProtectionChanged ) + { + GetProtectionL( iLastProtectionLevel ); + } + if ( aProtectionLevel == iLastProtectionLevel ) + { + iProtectionChanged = EFalse; + } + else + { + iProtectionChanged = ETrue; + } + + // Read current metadata without protection bits. + TUint32 currentMetadata = + ( ( TUint32 )( iMetadataRecord->iMetadata ) & ( ~KDestProtectionLevelMask ) ); + // Add new protection bits. + iMetadataRecord->iMetadata = + currentMetadata | ( aProtectionLevel << KBitsToShiftDestProtectionLevel ); + + iMetadataRecordStatus = ECmmRecordStatusModified; + iStatus = ECmmDestinationStatusChanged; + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETPROTECTIONL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Return true if protection level has been changed. +// --------------------------------------------------------------------------- +// +TBool CCmmDestinationInstance::ProtectionChanged() + { + return iProtectionChanged; + } + +// --------------------------------------------------------------------------- +// Return the previous valid protection level of this connection method +// instance. +// --------------------------------------------------------------------------- +// +CMManager::TProtectionLevel CCmmDestinationInstance::LastProtectionLevel() + { + return iLastProtectionLevel; + } + +// --------------------------------------------------------------------------- +// Return the protection level currently set into this destination instance. +// --------------------------------------------------------------------------- +// +CMManager::TProtectionLevel CCmmDestinationInstance::CurrentProtectionLevel() + { + return iCurrentProtectionLevel; + } + +// --------------------------------------------------------------------------- +// Adds a connection method into this destination. Returns the index (priority) +// in the connection method array where the connection method was added. +// Embedded destinations can not be added with this method, use +// AddEmbeddedDestinationL() instead. +// --------------------------------------------------------------------------- +// +TInt CCmmDestinationInstance::AddConnMethodL( + const CCmmConnMethodInstance& aConnMethodInstance ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_ADDCONNMETHODL_ENTRY ); + + TUint32 connMethodId( aConnMethodInstance.GetId() ); + TUint32 bearerType( aConnMethodInstance.GetBearerType() ); + + // Check that the connection method is not an embedded destination. + if ( bearerType == KUidEmbeddedDestination ) + { + User::Leave( KErrArgument ); + } + + // Check that the connection method is not already inside this destination. + for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ ) + { + if ( connMethodId == iConnMethodItemArray[i].iId ) + { + User::Leave( KErrAlreadyExists ); + } + } + + // Remove the connection method from delete list, if found there. + for ( TInt i = 0; i < iConnMethodsToBeDeleted.Count(); i++ ) + { + if ( connMethodId == iConnMethodsToBeDeleted[i] ) + { + iConnMethodsToBeDeleted.Remove( i ); + break; + } + } + + // Get the priority value of this connection method according to bearer. + TUint bearerPriority( 0 ); + iCache->BearerPriorityFromIapRecordL( + ( CommsDat::CCDIAPRecord* )aConnMethodInstance.GetPluginDataInstance()->iGenRecordArray[KIapRecordIndex], + bearerPriority ); + TCmmConnMethodItem item( connMethodId, bearerType, bearerPriority, 0 ); + + // Find out the correct position for the connection method inside this + // destination. + TInt index = iConnMethodItemArray.Count(); + for ( TInt i = index - 1; i >= 0; i-- ) + { + if ( iConnMethodItemArray[i].iBearerPriority == + CMManager::KDataMobilitySelectionPolicyPriorityWildCard ) + { + index = i; + continue; + } + if ( iConnMethodItemArray[i].iBearerPriority == bearerPriority ) + { + break; + } + if ( iConnMethodItemArray[i].iBearerPriority > bearerPriority ) + { + index = i; + } + } + // Add the connection method item into this destination at the correct + // position (priority). + iConnMethodItemArray.InsertL( item, index ); + + SetStatus( ECmmDestinationStatusChanged ); + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_ADDCONNMETHODL_EXIT ); + return index; + } + +// --------------------------------------------------------------------------- +// Adds an embedded destination into this destination. Returns the index in +// the connection method array where the connection method was added. +// --------------------------------------------------------------------------- +// +TInt CCmmDestinationInstance::AddEmbeddedDestinationL( + const CCmmDestinationInstance& aEmbeddedDestinationInstance ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_ADDEMBEDDEDDESTINATIONL_ENTRY ); + + TUint32 embeddedDestinationId( aEmbeddedDestinationInstance.GetId() ); + + // Check that not adding itself. + if ( embeddedDestinationId == iId ) + { + User::Leave( KErrArgument ); + } + + // Check that the embedded destination is not already an embedded + // destination in this destination. + if ( HasEmbeddedWithId( embeddedDestinationId ) ) + { + User::Leave( KErrAlreadyExists ); + } + + // A destination can not be added into a destination that is itself an + // embedded destination. + if ( iCache->DestinationIsEmbedded( iId ) ) + { + User::Leave( KErrNotSupported ); + } + + // A destination can not be added into a destination that already has an + // embedded destination. + if ( HasEmbedded() || iCache->DestinationHasEmbedded( iId ) ) + { + User::Leave( KErrNotSupported ); + } + + // A destination that already has an embedded destination can not be added + // into a destination. + if ( aEmbeddedDestinationInstance.HasEmbedded() || + iCache->DestinationHasEmbedded( embeddedDestinationId ) ) + { + User::Leave( KErrNotSupported ); + } + + // Check session side destination instances for all clients. + // - Check that any destination instance does not contain aDestinationId as + // embedded destination. + // - Check that any destination instance for aEmbeddedDestinationId does + // not contain an embedded destination. + if ( iCmmSession->EmbeddedDestinationConflictsFromAllSessions( iId, embeddedDestinationId ) ) + { + User::Leave( KErrAlreadyExists ); + } + + // Add the embedded destination at the end of the connection method item array. + TInt index = iConnMethodItemArray.Count(); + TCmmConnMethodItem item( + embeddedDestinationId, + KUidEmbeddedDestination, + CMManager::KDataMobilitySelectionPolicyPriorityWildCard, + 0 ); + iConnMethodItemArray.AppendL( item ); + + SetStatus( ECmmDestinationStatusChanged ); + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_ADDEMBEDDEDDESTINATIONL_EXIT ); + return index; + } + +// --------------------------------------------------------------------------- +// Delete a connection method that belongs to this destination. If the +// connection method belongs to any other destination, it is only removed from +// this destination and not deleted. Does not call update. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::DeleteConnMethodFromDestinationL( + const CCmmConnMethodInstance& aConnMethodInstance ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_DELETECONNMETHODFROMDESTINATIONL_ENTRY ); + + // Check that the connection method is inside this destination. + TUint32 connMethodId( aConnMethodInstance.GetId() ); + TInt index( KErrNotFound ); + for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ ) + { + if ( connMethodId == iConnMethodItemArray[i].iId ) + { + index = i; + break; + } + } + if ( index < 0 ) + { + User::Leave( KErrArgument ); + } + + // Check if the connection method removal is blocked by any virtual IAPs. + if ( ConnMethodInDestinationButLocked( connMethodId ) ) + { + User::Leave( KErrLocked ); + } + + // Check if any virtual IAP points to this connection method, thus blocking + // the delete. + if ( iCache->ConnMethodPointedToByVirtualIap( connMethodId ) ) + { + User::Leave( KErrLocked ); + } + + // Check that the connection method is not in use by an active connection. + if ( iCache->CheckIfCmConnected( connMethodId ) ) + { + User::Leave( KErrInUse ); + } + + // This will also remove an embedded destination. + iConnMethodItemArray.Remove( index ); + SetStatus( ECmmDestinationStatusChanged ); + + // If this connection method is an embedded destination, then removing it + // from this destination is enough. The destination is not deleted. + if ( aConnMethodInstance.GetBearerType() != KUidEmbeddedDestination ) + { + // Add connection method to delete list only if not referenced from any + // other destination (in database or in any destination handles for the + // client currently beeing served). + if ( !iCache->ConnMethodInOtherDestination( connMethodId, iId ) && + !iCmmSession->ConnMethodInOtherDestination( connMethodId, iId ) ) + { + if ( iConnMethodsToBeDeleted.Find( connMethodId ) == KErrNotFound ) + { + iConnMethodsToBeDeleted.AppendL( connMethodId ); + } + } + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_DELETECONNMETHODFROMDESTINATIONL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Remove a connection method from this destination. If the second attribute +// aTestIfConnected is false, the test to check if connection method is in use +// is skipped. In this case this should have been already tested by the caller. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::RemoveConnMethodFromDestinationL( + const CCmmConnMethodInstance& aConnMethodInstance, + const TBool& aTestIfConnected ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_REMOVECONNMETHODFROMDESTINATIONL_ENTRY ); + + // Check that the connection method is inside this destination. + TUint32 connMethodId( aConnMethodInstance.GetId() ); + TInt index( KErrNotFound ); + for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ ) + { + if ( connMethodId == iConnMethodItemArray[i].iId ) + { + index = i; + break; + } + } + if ( index < 0 ) + { + User::Leave( KErrArgument ); + } + + // Check if the connection method removal is blocked by any virtual IAPs. + if ( ConnMethodInDestinationButLocked( connMethodId ) ) + { + User::Leave( KErrLocked ); + } + + if ( aTestIfConnected ) + { + // Check that the connection method is not in use by an active connection. + if ( iCache->CheckIfCmConnected( connMethodId ) ) + { + User::Leave( KErrInUse ); + } + } + + // This will also remove an embedded destination. + iConnMethodItemArray.Remove( index ); + SetStatus( ECmmDestinationStatusChanged ); + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_REMOVECONNMETHODFROMDESTINATIONL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Modifies the priority of a connection method inside this destination. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::ModifyConnMethodPriorityL( + const CCmmConnMethodInstance& aConnMethodInstance, + TUint aIndex ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_MODIFYCONNMETHODPRIORITYL_ENTRY ); + + // Check if the connection method is in this destination. Also store the + // current index of the connection method. + TInt oldIndex( KErrNotFound ); + for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ ) + { + if ( iConnMethodItemArray[i].iId == aConnMethodInstance.GetId() ) + { + oldIndex = i; + break; + } + } + if ( oldIndex < 0 ) + { + User::Leave( KErrArgument ); + } + + // If connection method is an embedded destination, just return silently. + if ( aConnMethodInstance.GetBearerType() == KUidEmbeddedDestination ) + { + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_MODIFYCONNMETHODPRIORITYL_EXIT ); + return; + } + + //TODO, if CM is virtual IAP that points into DESTINATION, just return silently. + // + // + + // Check index range. + if ( aIndex >= iConnMethodItemArray.Count() ) + { + User::Leave( KErrArgument ); + } + + // If the given index points to any wildcard priority connection method, + // adjust it so it points to the last priority position. + TUint numberOfConnMethodsWithPriority( NumberOfConnMethodsWithPriority() ); + if ( aIndex >= numberOfConnMethodsWithPriority ) + { + if ( numberOfConnMethodsWithPriority == 0 ) + { + // Can't be 0, since aConnMethodInstance is not a wildcard IAP and + // is in the array. + ASSERT( 0 ); + User::Leave( KErrCorrupt ); + } + aIndex = numberOfConnMethodsWithPriority--; + } + + // Check if the priority is changing from current. + if ( oldIndex == aIndex ) + { + OstTraceFunctionExit0( DUP1_CCMMDESTINATIONINSTANCE_MODIFYCONNMETHODPRIORITYL_EXIT ); + return; + } + + // Change the location of the connection method to reflect the new priority. + TCmmConnMethodItem item = iConnMethodItemArray[oldIndex]; + iConnMethodItemArray.Remove( oldIndex ); + iConnMethodItemArray.InsertL( item, ( TInt )aIndex ); + + SetStatus( ECmmDestinationStatusChanged ); + + OstTraceFunctionExit0( DUP2_CCMMDESTINATIONINSTANCE_MODIFYCONNMETHODPRIORITYL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Finds a connection method instance that belongs to the same session and +// matches the provided ID. Return NULL if no match is found. +// --------------------------------------------------------------------------- +// +CCmmConnMethodInstance* CCmmDestinationInstance::FindConnMethodInstanceFromSessionById( + const TUint32& aConnMethodId ) const + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_FINDCONNMETHODINSTANCEFROMSESSIONBYID_ENTRY ); + + CCmmConnMethodInstance* connMethodInstance = iCmmSession-> + FindConnMethodInstanceById( aConnMethodId ); + + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_FINDCONNMETHODINSTANCEFROMSESSIONBYID_EXIT ); + return connMethodInstance; + } + +// --------------------------------------------------------------------------- +// Finds a destination instance that belongs to the same session and matches +// the provided ID. Return NULL if no match is found. +// --------------------------------------------------------------------------- +// +CCmmDestinationInstance* CCmmDestinationInstance::FindDestinationInstanceFromSessionById( + const TUint32& aDestinationId ) const + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_FINDDESTINATIONINSTANCEFROMSESSIONBYID_ENTRY ); + + CCmmDestinationInstance* destInstance = + iCmmSession->FindDestinationInstanceById( aDestinationId ); + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_FINDDESTINATIONINSTANCEFROMSESSIONBYID_EXIT ); + return destInstance; + } + +// --------------------------------------------------------------------------- +// Check from all open destination handles in the same session if the given +// connection method is inside any of them. The given destination is skipped. +// --------------------------------------------------------------------------- +// +TBool CCmmDestinationInstance::ConnMethodInOtherDestinationInSession( + const TUint32& aConnMethodId, + const TUint32& aDestinationId ) const + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_CONNMETHODINOTHERDESTINATIONINSESSION_ENTRY ); + + TBool inOtherSession = iCmmSession-> + ConnMethodInOtherDestination( aConnMethodId, aDestinationId ); + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_CONNMETHODINOTHERDESTINATIONINSESSION_EXIT ); + return inOtherSession; + } + +// --------------------------------------------------------------------------- +// Check if the given connection method is in this destination. Include +// embedded destinations. +// --------------------------------------------------------------------------- +// +TBool CCmmDestinationInstance::ValidConnMethodIdInDestinationIncludeEmbedded( const TUint32& aConnMethodId ) const + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_VALIDCONNMETHODIDINDESTINATIONINCLUDEEMBEDDED_ENTRY ); + + TBool validity( EFalse ); + if ( aConnMethodId > 0 ) + { + for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ ) + { + if ( iConnMethodItemArray[i].iId == aConnMethodId ) + { + validity = ETrue; + break; + } + } + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_VALIDCONNMETHODIDINDESTINATIONINCLUDEEMBEDDED_EXIT ); + return validity; + } + +// --------------------------------------------------------------------------- +// Check if the given connection method is inside this destination and if it +// is in a 'locked' status. A locked connection method can't be deleted nor +// removed from the destination. A connection method becomes locked if it is +// the only remaining connection method in a destination and a virtual IAP +// points into that destination. +// --------------------------------------------------------------------------- +// +TBool CCmmDestinationInstance::ConnMethodInDestinationButLocked( + const TUint32& aConnMethodId ) const + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_CONNMETHODINDESTINATIONBUTLOCKED_ENTRY ); + + TBool result( EFalse ); + if ( iConnMethodItemArray.Count() == 1 ) + { + if ( iConnMethodItemArray[0].iId == aConnMethodId ) + { + if ( iCache->DestinationPointedToByVirtualIap( iId ) ) + { + result = ETrue; + } + } + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_CONNMETHODINDESTINATIONBUTLOCKED_EXIT ); + return result; + } + +// --------------------------------------------------------------------------- +// Counts how many connection methods that require priority information are +// currently in this destination. This excludes any virtual IAPs that point to +// a destination or any embedded destinations from the count. Assumes the +// connection method array is in order so all wildcard priority IAPs are at the +// end of the list. +// --------------------------------------------------------------------------- +// +TUint CCmmDestinationInstance::NumberOfConnMethodsWithPriority() const + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_NUMBEROFCONNMETHODSWITHPRIORITY_ENTRY ); + + TUint count( iConnMethodItemArray.Count() ); + + for ( TUint i = 0; i < iConnMethodItemArray.Count(); i++ ) + { + //TODO, add virtual IAP pointing to SNAP check. + if ( iConnMethodItemArray[i].iBearerType == KUidEmbeddedDestination ) + { + count = i; + break; + } + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_NUMBEROFCONNMETHODSWITHPRIORITY_EXIT ); + return count; + } + +// --------------------------------------------------------------------------- +// Check if this destination has an embedded destination. Checks the current +// (possibly unsaved) status of this destination handle, not the current status +// in database. +// --------------------------------------------------------------------------- +// +TBool CCmmDestinationInstance::HasEmbedded() const + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_HASEMBEDDED_ENTRY ); + + TBool result( EFalse ); + + // If there is an embedded destination, it will be at the very last + // position in the connection method item array. + TInt index = iConnMethodItemArray.Count() - 1; + if ( index >= 0 ) + { + if ( iConnMethodItemArray[index].iBearerType == KUidEmbeddedDestination ) + { + result = ETrue; + } + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_HASEMBEDDED_EXIT ); + return result; + } + +// --------------------------------------------------------------------------- +// Check if this destination has an embedded destination with the specified ID. +// Checks the current (possibly unsaved) status of this destination handle, not +// the current status in database. +// --------------------------------------------------------------------------- +// +TBool CCmmDestinationInstance::HasEmbeddedWithId( const TUint32& aDestinationId ) const + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_HASEMBEDDEDWITHID_ENTRY ); + + TBool result( EFalse ); + + // If there is an embedded destination, it will be at the very last + // position in the connection method item array. + TInt index = iConnMethodItemArray.Count() - 1; + if ( index >= 0 ) + { + // No need to check bearer, since ID will not match anyway if the last + // item is not an embedded destination. + if ( iConnMethodItemArray[index].iId == aDestinationId ) + { + result = ETrue; + } + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_HASEMBEDDEDWITHID_EXIT ); + return result; + } + +// --------------------------------------------------------------------------- +// After update/delete to database, refresh temporary ID to real ID if +// necessary and refresh status information for any related handles for +// all client sessions. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::RefreshHandlesForAllSessions( const TCmmIdStruct& aIdStruct ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_REFRESHHANDLESFORALLSESSIONS_ENTRY ); + + iCmmSession->RefreshHandlesForAllSessions( aIdStruct ); + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_REFRESHHANDLESFORALLSESSIONS_EXIT ); + } + +// --------------------------------------------------------------------------- +// If the destination contains a connection method with matching temporary ID, +// updates the ID to real ID. This is done after the connection method has been +// successfully saved into the database. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::RefreshConnMethodId( const TCmmIdStruct& aIdStruct ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_REFRESHCONNMETHODID_ENTRY ); + + for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ ) + { + if ( iConnMethodItemArray[i].iId == aIdStruct.iTemporaryId ) + { + iConnMethodItemArray[i].iId = aIdStruct.iRealId; + break; + } + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_REFRESHCONNMETHODID_EXIT ); + } + +// --------------------------------------------------------------------------- +// Called after this destination has been updated and database transaction has +// completed successfully. Sets the internal state of this destination instance +// to reflect the new valid state. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::UpdateSuccessful() + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_UPDATESUCCESSFUL_ENTRY ); + + SetStatus( ECmmDestinationStatusValid ); + SetStatusForAllRecords( ECmmRecordStatusLoaded ); + iConnMethodsToBeDeleted.Reset(); + iProtectionChanged = EFalse; + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_UPDATESUCCESSFUL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Checks if all mandatory records contain data and are ready to be saved into +// database. +// --------------------------------------------------------------------------- +// +TBool CCmmDestinationInstance::AllMandatoryRecordsContainData() const + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_ALLMANDATORYRECORDSCONTAINDATA_ENTRY ); + + TBool result( ETrue ); + + if ( iNetworkRecordStatus != ECmmRecordStatusLoaded && + iNetworkRecordStatus != ECmmRecordStatusExpired && + iNetworkRecordStatus != ECmmRecordStatusModified ) + { + result = EFalse; + } + if ( iDestApRecordStatus != ECmmRecordStatusLoaded && + iDestApRecordStatus != ECmmRecordStatusExpired && + iDestApRecordStatus != ECmmRecordStatusModified ) + { + result = EFalse; + } + if ( iMetadataRecordStatus != ECmmRecordStatusLoaded && + iMetadataRecordStatus != ECmmRecordStatusExpired && + iMetadataRecordStatus != ECmmRecordStatusModified ) + { + result = EFalse; + } + if ( !iNetworkRecord || !iDestApRecord || !iMetadataRecord ) + { + result = EFalse; + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_ALLMANDATORYRECORDSCONTAINDATA_EXIT ); + return result; + } + +// --------------------------------------------------------------------------- +// Loads a certain type of record from database if it is not up-to-date. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::RefreshRecordL( TCmmDbRecords aRecordType ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_REFRESHRECORDL_ENTRY ); + + TCmmRecordStatus status( ECmmRecordStatusBlank ); + switch ( aRecordType ) + { + case ECmmDestNetworkRecord: + status = iNetworkRecordStatus; + break; + case ECmmDestApRecord: + status = iDestApRecordStatus; + break; + case ECmmDestMetadataRecord: + status = iMetadataRecordStatus; + break; + default: + User::Leave( KErrCorrupt ); // Error, unknown type. + break; + } + + switch ( status ) + { + // Fallthrough intended + case ECmmRecordStatusBlank: + case ECmmRecordStatusExpired: + iCache->LoadDestinationRecordL( *this, aRecordType ); + break; + case ECmmRecordStatusLoaded: + case ECmmRecordStatusModified: + // Record is up-to-date. + break; + case ECmmRecordStatusUnsaved: + default: + User::Leave( KErrCorrupt ); // Error, unknown status. + break; + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_REFRESHRECORDL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Loads all records from database that are not up-to-date. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::LoadAllRecordsL() + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_LOADALLRECORDSL_ENTRY ); + + RefreshRecordL( ECmmDestNetworkRecord ); + RefreshRecordL( ECmmDestApRecord ); + RefreshRecordL( ECmmDestMetadataRecord ); + + if ( !iNetworkRecord || !iDestApRecord || !iMetadataRecord ) + { + User::Leave( KErrCorrupt ); + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_LOADALLRECORDSL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Set metadata of type ESnapMetadataInternet. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::SetMetadataInternetL( const TUint32& aMetadata ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETMETADATAINTERNETL_ENTRY ); + + if ( aMetadata ) + { + if ( iCache->DestinationExistsWithMetadataLocalizedL( *this, CMManager::ELocalisedDestInternet ) ) + { + User::Leave( KErrAlreadyExists ); + } + // Clear ESnapMetadataHiddenAgent-bit. + TUint32 value = iMetadataRecord->iMetadata & ( ~CMManager::ESnapMetadataHiddenAgent ); + + // Set old ESnapMetadataInternet-bit. + value = value | CMManager::ESnapMetadataInternet; + + // Clear ESnapMetadataDestinationIsLocalised-bits. + value = value & ( ~CMManager::ESnapMetadataDestinationIsLocalised ); + // Set ELocalisedDestInternet-value. + iMetadataRecord->iMetadata = value | ( CMManager::ELocalisedDestInternet << 4 ); + value = value | ( CMManager::ELocalisedDestInternet << 4 ); + + // Clear ESnapMetadataPurpose-bits. + value = value & ( ~CMManager::ESnapMetadataPurpose ); + // Set ESnapPurposeInternet-value. + iMetadataRecord->iMetadata = value | ( CMManager::ESnapPurposeInternet << 8 ); + } + else + { + // Clear old ESnapMetadataInternet-bit, ESnapMetadataDestinationIsLocalised-bits and CMManager::ESnapMetadataPurpose-bits. + TUint32 temp = ~( CMManager::ESnapMetadataInternet | CMManager::ESnapMetadataDestinationIsLocalised | CMManager::ESnapMetadataPurpose ); + iMetadataRecord->iMetadata = iMetadataRecord->iMetadata & temp; + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETMETADATAINTERNETL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Set metadata of type ESnapMetadataHighlight. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::SetMetadataHighlight( const TUint32& aMetadata ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETMETADATAHIGHLIGHTL_ENTRY ); + + // TODO: Old CmManager does not perform any duplicate checks when setting highlight. + // Now with single click this is not used anymore anyway. So I suggest we don't add any checks here. + if ( aMetadata ) + { + // Set ESnapMetadataHighlight-bit. + iMetadataRecord->iMetadata = iMetadataRecord->iMetadata | CMManager::ESnapMetadataHighlight; + } + else + { + // Clear ESnapMetadataHighlight-bit. + iMetadataRecord->iMetadata = iMetadataRecord->iMetadata & ( ~CMManager::ESnapMetadataHighlight ); + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETMETADATAHIGHLIGHTL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Set metadata of type ESnapMetadataHiddenAgent. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::SetMetadataHiddenAgentL( const TUint32& aMetadata ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETMETADATAHIDDENAGENTL_ENTRY ); + + if ( aMetadata ) + { + TUint32 metadataInternet( iMetadataRecord->iMetadata & CMManager::ESnapMetadataInternet ); + TUint32 metadataLocalized( ( iMetadataRecord->iMetadata & CMManager::ESnapMetadataDestinationIsLocalised ) >> 4 ); + TUint32 metadataPurpose( ( iMetadataRecord->iMetadata & CMManager::ESnapMetadataPurpose ) >> 8 ); + if ( metadataInternet || + ( metadataLocalized == CMManager::ELocalisedDestInternet ) || + ( metadataPurpose == CMManager::ESnapPurposeInternet ) ) + { + // Not allowed to set ESnapMetadataHiddenAgent if destination is localized or has purpose set. + User::Leave( KErrArgument ); + } + // Set ESnapMetadataHiddenAgent-bit. + iMetadataRecord->iMetadata = iMetadataRecord->iMetadata | CMManager::ESnapMetadataHiddenAgent; + } + else + { + // Clear ESnapMetadataHiddenAgent-bit. + iMetadataRecord->iMetadata = iMetadataRecord->iMetadata & ( ~CMManager::ESnapMetadataHiddenAgent ); + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETMETADATAHIDDENAGENTL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Set metadata of type ESnapMetadataDestinationIsLocalised. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::SetMetadataLocalizationL( const TUint32& aMetadata ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETMETADATALOCALIZATIONL_ENTRY ); + + // Check that aMetadata is within valid range. + if ( aMetadata > CMManager::ELocalisedDestIntranet ) + { + User::Leave( KErrArgument ); + } + + TUint32 temp = ~( CMManager::ESnapMetadataInternet | CMManager::ESnapMetadataDestinationIsLocalised | CMManager::ESnapMetadataPurpose ); + if ( aMetadata == CMManager::ENotLocalisedDest ) + { + // Clear old ESnapMetadataInternet-bit, ESnapMetadataDestinationIsLocalised-bits and ESnapMetadataPurpose-bits. + iMetadataRecord->iMetadata = iMetadataRecord->iMetadata & temp; + } + else + { + if ( iCache->DestinationExistsWithMetadataLocalizedL( *this, aMetadata ) ) + { + User::Leave( KErrAlreadyExists ); + } + + // Clear old ESnapMetadataInternet-bit, ESnapMetadataDestinationIsLocalised-bits and ESnapMetadataPurpose-bits. + TUint32 value = iMetadataRecord->iMetadata & temp; + switch ( aMetadata ) + { + case CMManager::ELocalisedDestInternet: + { + // Clear ESnapMetadataHiddenAgent-bit. + value = value & ( ~CMManager::ESnapMetadataHiddenAgent ); + // Set old ESnapMetadataInternet-bit. + value = value | CMManager::ESnapMetadataInternet; + // Set ESnapPurposeInternet-value. + value = value | ( CMManager::ESnapPurposeInternet << 8 ); + } + break; + case CMManager::ELocalisedDestWap: + { + // Set ESnapPurposeOperator-value. + value = value | ( CMManager::ESnapPurposeOperator << 8 ); + } + break; + case CMManager::ELocalisedDestMMS: + { + // Set ESnapMetadataHiddenAgent-bit. + value = value | CMManager::ESnapMetadataHiddenAgent; + // Set ESnapPurposeMMS-value. + value = value | ( CMManager::ESnapPurposeMMS << 8 ); + } + break; + case CMManager::ELocalisedDestIntranet: + { + // Set ESnapPurposeIntranet-value. + value = value | ( CMManager::ESnapPurposeIntranet << 8 ); + } + break; + default: + User::Leave( KErrArgument ); + break; + } + // Set ESnapMetadataDestinationIsLocalised-value. + iMetadataRecord->iMetadata = value | ( aMetadata << 4 ); + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETMETADATALOCALIZATIONL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Set metadata of type ESnapMetadataPurpose. +// --------------------------------------------------------------------------- +// +void CCmmDestinationInstance::SetMetadataPurposeL( const TUint32& aMetadata ) + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETMETADATAPURPOSEL_ENTRY ); + + // Check that aMetadata is within valid range. + if ( aMetadata > CMManager::ESnapPurposeIntranet ) + { + User::Leave( KErrArgument ); + } + + TUint32 temp = ~( CMManager::ESnapMetadataInternet | CMManager::ESnapMetadataDestinationIsLocalised | CMManager::ESnapMetadataPurpose ); + if ( aMetadata == CMManager::ESnapPurposeUnknown ) + { + // Clear old ESnapMetadataInternet-bit, ESnapMetadataDestinationIsLocalised-bits and ESnapMetadataPurpose-bits. + iMetadataRecord->iMetadata = iMetadataRecord->iMetadata & temp; + } + else + { + if ( iCache->DestinationExistsWithMetadataPurposeL( *this, aMetadata ) ) + { + User::Leave( KErrAlreadyExists ); + } + + // Clear old ESnapMetadataInternet-bit, ESnapMetadataDestinationIsLocalised-bits and ESnapMetadataPurpose-bits. + TUint32 value = iMetadataRecord->iMetadata & temp; + + switch ( aMetadata ) + { + case CMManager::ESnapPurposeInternet: + { + // Clear ESnapMetadataHiddenAgent-bit. + value = value & ( ~CMManager::ESnapMetadataHiddenAgent ); + // Set old ESnapMetadataInternet-bit. + value = value | CMManager::ESnapMetadataInternet; + // Set ELocalisedDestInternet-value. + value = value | ( CMManager::ELocalisedDestInternet << 4 ); + } + break; + case CMManager::ESnapPurposeOperator: + { + // Set ELocalisedDestWap-value. + value = value | ( CMManager::ELocalisedDestWap << 4 ); + } + break; + case CMManager::ESnapPurposeMMS: + { + // Set ESnapMetadataHiddenAgent-bit. + value = value | CMManager::ESnapMetadataHiddenAgent; + // Set ELocalisedDestMMS-value. + value = value | ( CMManager::ELocalisedDestMMS << 4 ); + } + break; + case CMManager::ESnapPurposeIntranet: + { + // Set ELocalisedDestIntranet-value. + value = value | ( CMManager::ELocalisedDestIntranet << 4 ); + } + break; + default: + User::Leave( KErrArgument ); + break; + } + // Set ESnapMetadataPurpose-value. + iMetadataRecord->iMetadata = value | ( aMetadata << 8 ); + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETMETADATAPURPOSEL_EXIT ); + } + +// --------------------------------------------------------------------------- +// Checks the current metadata for this destination, and verifies there is no +// other conflicting destinations in the database. +// --------------------------------------------------------------------------- +// +TBool CCmmDestinationInstance::ConflictingMetadataFoundL() + { + OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_CONFLICTINGMETADATAFOUNDL_ENTRY ); + + TBool result( EFalse ); + TUint32 metadataInternet( iMetadataRecord->iMetadata & CMManager::ESnapMetadataInternet ); + TUint32 metadataLocalized( ( iMetadataRecord->iMetadata & CMManager::ESnapMetadataDestinationIsLocalised ) >> 4 ); + TUint32 metadataPurpose( ( iMetadataRecord->iMetadata & CMManager::ESnapMetadataPurpose ) >> 8 ); + + if ( metadataPurpose ) + { + // Some metadata is set, need to check conflicts in database. + switch ( metadataPurpose ) + { + // Fallthrough intended. + case CMManager::ESnapPurposeInternet: + case CMManager::ESnapPurposeOperator: + case CMManager::ESnapPurposeMMS: + case CMManager::ESnapPurposeIntranet: + result = iCache->DestinationExistsWithMetadataPurposeL( *this, metadataPurpose ); + break; + default: + User::Leave( KErrCorrupt ); // Invalid metadata. + break; + } + } + else if ( metadataLocalized ) + { + // Error, metadataPurpose was not set. Continue anyway. + switch ( metadataLocalized ) + { + // Fallthrough intended. + case CMManager::ELocalisedDestInternet: + case CMManager::ELocalisedDestWap: + case CMManager::ELocalisedDestMMS: + case CMManager::ELocalisedDestIntranet: + result = iCache->DestinationExistsWithMetadataLocalizedL( *this, metadataLocalized ); + break; + default: + User::Leave( KErrCorrupt ); // Invalid metadata. + break; + } + } + else if ( metadataInternet ) + { + // Error, metadataPurpose and metadataLocalized was not set. Continue anyway. + result = iCache->DestinationExistsWithMetadataLocalizedL( *this, CMManager::ELocalisedDestInternet ); + } + + OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_CONFLICTINGMETADATAFOUNDL_EXIT ); + return result; + } + +// End of file