diff -r 000000000000 -r 094583676ce7 wvuing/wvuipresence/src/CCAPEngPresenceManager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wvuing/wvuipresence/src/CCAPEngPresenceManager.cpp Thu Dec 17 08:41:52 2009 +0200 @@ -0,0 +1,2064 @@ +/* +* Copyright (c) 2002-2005 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: Manager for presence operations (fetcher/notifier/publisher). +* +*/ + + + +// INCLUDE FILES +#include "CCAPEngPresenceManager.h" +#include "CAPresenceDefinitions.h" +#include "CAPresenceUtils.h" +#include "CCAPEngListManager.h" + +// Contact handling +#include "CCAStorageManagerFactory.h" +#include "MCAStoredContacts.h" + +#include "impsbuilddefinitions.h" + +#include "MCAContactList.h" + +#include "MCAStoredContact.h" + +#include "ChatDebugPrint.h" + +#include "MCAPresenceObserver.h" +#include "MCAWatcherObserver.h" +#include "MCASettings.h" + +#include "CCAPresenceErrors.h" +#include "CAPresenceConst.h" +#include "MCAPresence.h" +#include "MCAContactLists.h" +#include "TCAWrappers.h" + +#include "MCAReactiveAuthObserver.h" +#include "SServerPrefers.h" +#include "TDecodeAttrParams.h" + +#include "ImpsCSPAllErrors.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::CCAPEngPresenceManager +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CCAPEngPresenceManager::CCAPEngPresenceManager() + : iAuthMode( KUndefined ), + iNetworkState( KUndefined ), + iPEngAPIInitialized( EFalse ), + iObserverQueued( EFalse ), + iCachedStatus( EFalse ), + iAttributeProcessing( ETrue ) + { + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::ConstructL( MCASettings* aApplicationSettings ) + { + // Set settings API + SetSettingsAPIL( aApplicationSettings ); + + // Assign attributes that we are handling + ResetAttributesL( EFalse ); + + // Create detailed error container + iErrors = CCAPresenceErrors::NewL(); + + iIdle = CIdle::NewL( CActive::EPriorityIdle ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CCAPEngPresenceManager* CCAPEngPresenceManager::NewL( + MCASettings* aApplicationSettings ) + { + CCAPEngPresenceManager* self = new( ELeave ) CCAPEngPresenceManager; + + CleanupStack::PushL( self ); + self->ConstructL( aApplicationSettings ); + CleanupStack::Pop( self ); + + return self; + } + + +// Destructor +CCAPEngPresenceManager::~CCAPEngPresenceManager() + { + delete iPEngAttributeTransaction; + delete iListManager; + delete iPEngAttributeStore; + delete iErrors; + if ( iOwnPresenceNotifier ) + { + iOwnPresenceNotifier->RemoveObserver( *this ); + } + delete iOwnPresenceNotifier; + delete iCachedStatusText; + + iAttributes.Close(); + + if ( iRANotifier ) + { + iRANotifier->RemoveObserver( *this ); + iRANotifier->Stop(); + } + + delete iRAStore; + delete iRANotifier; + delete iRATransaction; + + delete iSessionSlotID; + + iOwnStates.ResetAndDestroy(); + iPresenceStates.ResetAndDestroy(); + iFetchObjects.ResetAndDestroy(); + + TInt count( iAttrArrays.Count() ); + for ( TInt a( 0 ); a < count; ++a ) + { + iAttrArrays[ a ].iArray.ResetAndDestroy(); + } + iAttrArrays.Close(); + + delete iIdle; + } + + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::AddWatcherL +// Sets watcher flag for given contact +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::AddWatcherL( const TDesC& aWVId ) + { + CHAT_DP_TXT( "CCAPEngPresenceManager::AddWatcherL" ); + CCAStorageManagerFactory::ContactListInterfaceL()->SetWatched( aWVId, ETrue ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::GetOnlineFriendsL +// Fetches list of online-friends +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::GetOnlineFriendsL( CDesCArray &aOnlineList, + TBool aFetchFromNetwork ) + { + CHAT_DP_TXT( "CCAPEngPresenceManager::GetOnlineFriendsL()...starts" ); + + CPtrCArray* friends = CAPresenceUtils::GenerateFriendsArrayLC( + CCAStorageManagerFactory::ContactListInterfaceL() ); + + // Reset given array + aOnlineList.Reset(); + + // update our lists + if ( aFetchFromNetwork ) + { + CHAT_DP_TXT( "CCAPEngPresenceManager::GetOnlineFriendsL starting \ + network fetch" ); + FetchAttributesL( *friends, &aOnlineList, NULL, NULL, EFalse ); + } + + // Populate aOnlineList with online friends + TInt friendCount( friends->Count() ); + MCAStoredContact* contact = NULL; + + for ( TInt i( 0 ); i < friendCount; ++i ) + { + contact = CCAStorageManagerFactory::ContactListInterfaceL()-> + FindAnyContact( ( *friends )[i] ); + if ( contact ) + { + TStorageManagerGlobals::TPresenceStatus status = + contact->OnlineStatus(); + if ( status == TStorageManagerGlobals::EOnline || + status == TStorageManagerGlobals::EAway || + status == TStorageManagerGlobals::EBusy ) + { + aOnlineList.AppendL( contact->UserId() ); + } + } + } + + CleanupStack::PopAndDestroy( friends ); + + CHAT_DP_TXT( "CCAPEngPresenceManager::GetOnlineFriendsL...over" ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::GetOnlineUsersL +// Fetches list of online users from given user-list +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::GetOnlineUsersL( const CDesCArray &aUserList, + CDesCArray *aOnlineList, + CDesCArray *aOffLineList, + TBool aUpdateStorage /*= EFalse*/ ) + { + CHAT_DP( D_CHAT_LIT( "CCAPEngPresenceManager::GetOnlineUsersL, \ + aUserList.Count() = %d, &aOnlineList = %d, \ + &aOffLineList = %d" ), + aUserList.Count(), aOnlineList, aOffLineList ); + + FetchAttributesL( aUserList, aOnlineList, aOffLineList, NULL, + aUpdateStorage ); + + CHAT_DP_TXT( "CCAPEngPresenceManager::GetOnlineUsersL done" ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::PresenceObserver +// Returns presence-observer pointer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +MCAPresenceObserver* CCAPEngPresenceManager::PresenceObserver() const + { + return iPresenceObserver; + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::RefreshFriendsL +// Refreshes the presence status of friends according to refresh-flags +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::RefreshFriendsL() + { + // Create needed MDesCArray-based array for presence operations + CPtrCArray* contactsArray = CAPresenceUtils::GenerateFriendsArrayLC( + CCAStorageManagerFactory::ContactListInterfaceL()/*, EFalse*/ ); + FetchAttributesL( *contactsArray, NULL, NULL, NULL, ETrue ); + CleanupStack::PopAndDestroy( contactsArray ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::SubscribeFriendsL +// Subscribes friends based on update-flag +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::SubscribeFriendsL( const TSubscribeMode aMode ) + { + CHAT_DP( D_CHAT_LIT( "CCAPEngPresenceManager::SubscribeFriendsL, mode = %d" ), + aMode ); + + if ( !iPEngAPIInitialized ) + { + return; + } + iListManager->SubscribeListsL( aMode == MCAPresence::ESubscribe ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::ContactLists +// Returns contact-list-handling interface +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +MCAContactLists* CCAPEngPresenceManager::ContactLists() + { + return iListManager; + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::LastOperationResult +// Returns last operation's error results +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +const CCAPresenceErrors& CCAPEngPresenceManager::LastOperationResult() const + { + return *iErrors; + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::SettingsAPI +// Return settings-API +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +MCASettings* CCAPEngPresenceManager::SettingsAPI() const + { + return iApplicationSettings; + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::SetSettingsAPIL +// Sets settings API +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::SetSettingsAPIL( + MCASettings* aApplicationSettings ) + { + // CCAPEngPresenceManager need settings API to function correctly + if ( !iApplicationSettings && !aApplicationSettings ) + { + User::Leave( ECANoSettingsAPI ); + } + + // If settings API handle provided, then update current handle + if ( aApplicationSettings ) + { + iApplicationSettings = aApplicationSettings; + } + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::RemoveWatcherL +// Removes watcher from given user +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::RemoveWatcherL( const TDesC &aWVId ) + { + CHAT_DP_TXT( "CCAPEngPresenceManager::RemoveWatcherL" ); + CCAStorageManagerFactory::ContactListInterfaceL()-> + SetWatched( aWVId, EFalse ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::SetPresenceObserver +// Sets presence observer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::SetPresenceObserver( + MCAPresenceObserver* aObserver ) + { + iPresenceObserver = aObserver; + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::SetWatcherObserver +// Sets watcher observer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::SetWatcherObserver( MCAWatcherObserver* aObserver ) + { + iWatcherObserver = aObserver; + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::HandleNetworkStateL +// To be called when network state changes +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::HandleNetworkStateL( TNetworkStatus aState, + const SServerPrefers& aServerPreferences, + CPEngNWSessionSlotID2* aSessionSlotID ) + { + CHAT_DP_FUNC_ENTER( "CCAPEngPresenceManager::HandleNetworkState" ); + + // read own states from resource + CAPresenceUtils::ReadStatesFromResourceL( + RSC_CHAT_VARIATION_OWN_PRESENCE_STATES, iOwnStates ); + + // read incoming presence states from resource + CAPresenceUtils::ReadStatesFromResourceL( + RSC_CHAT_VARIATION_PRESENCE_STATES, iPresenceStates ); + + iServerPrefers = aServerPreferences; + iAliasUsed = aServerPreferences.iAliasUsed; + + if ( aState != EUpdateBrand ) + { + // notification of branding must not keep the state + // changed, but should be returned to the existing state + iNetworkState = aState; + } + + if ( aState == ELoggedIn ) + { + // initialize own presence observer, if one is queued + InitializeOwnPresenceObserverL(); + // check if we have cached values + if ( iCachedAppSettingsAuthValue ) + { + SetPresenceAuthorizationL( iCachedAppSettingsAuthValue ); + iCachedAppSettingsAuthValue = 0; + } + if ( iCachedStatus ) + { + ChangeStatusL( iCachedPresenceStatus, *iCachedStatusText ); + iCachedStatus = EFalse; + delete iCachedStatusText; + iCachedStatusText = NULL; + } + else if ( iCachedStatusText ) + { + ChangeStatusMessageL( *iCachedStatusText ); + delete iCachedStatusText; + iCachedStatusText = NULL; + } + } + + // update own state and notify observers + NotifyOwnPresenceObserverL(); + + if ( aState == EUpdateBrand ) + { + iRAUsed = aServerPreferences.iReactiveAuthorization; + iAliasUsed = aServerPreferences.iAliasUsed; + return; + } + + if ( iListManager ) + { + iListManager->SetLoggedIn( iNetworkState == ELoggedIn, aSessionSlotID ); + } + + if ( !IsLoggedIn() ) + { + // logging out + CancelPendingRequests(); + + // stop the RA notifier + if ( iRANotifier ) + { + iRANotifier->Stop(); + } + } + + CHAT_DP_FUNC_DONE( "CCAPEngPresenceManager::HandleNetworkState" ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::InitializePEngAPIL +// Handles changes in setting values +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::InitializePEngAPIL() + { + // we can straight delete the old one, since + // if creating does not work, then we cannot do anything anyway + delete iListManager; + iListManager = NULL; + // Create list manager + iListManager = CCAPEngListManager::NewL( + *iApplicationSettings, + iAttributes, + *this, // presence observer + iSessionSlotID, + *this ); // presence updater + + delete iPEngAttributeTransaction; + iPEngAttributeTransaction = NULL; + // Create publisher + iPEngAttributeTransaction = + CPEngAttributeTransaction2::NewL( *iSessionSlotID ); + + delete iPEngAttributeStore; + iPEngAttributeStore = NULL; + // Create attribute store + iPEngAttributeStore = CPEngAttributeStore2::NewL( *iSessionSlotID ); + + // reactive authorization stuffs + delete iRAStore; + iRAStore = NULL; + iRAStore = CPEngReactAuthStore::NewL( *iSessionSlotID ); + + delete iRANotifier; + iRANotifier = NULL; + iRANotifier = CPEngReactAuthNotifier::NewL( *iSessionSlotID ); + iRANotifier->AddObserver( *this ); + + delete iRATransaction; + iRATransaction = NULL; + iRATransaction = CPEngReactAuthTransaction::NewL( *iSessionSlotID ); + + iPEngAPIInitialized = ETrue; + + MCAStoredContacts* contacts = + CCAStorageManagerFactory::ContactListInterfaceL(); + contacts->OwnStatus().SetUserIdL( iSessionSlotID->UserId() ); + contacts->OwnStatus().SetAliasL( KNullDesC ); + iListManager->SetLoggedIn( ETrue, iSessionSlotID ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::HandleSettingsChangeL +// Handles changes in setting values +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::HandleSettingsChangeL( TInt aChangedSettingEnum ) + { + if ( ! IsLoggedIn() ) + { + // we might not have a server, unless we're logged in, so we can't do + // any presence stuff + return; + } + + // Presence update mode change + if ( aChangedSettingEnum == MCASettings::EAutomaticPresenceUpdate ) + { + if ( iApplicationSettings->Value( + MCASettings::EAutomaticPresenceUpdate ) ) + { + SubscribeFriendsL( MCAPresence::ESubscribe ); + } + else + { + SubscribeFriendsL( MCAPresence::EUnSubscribe ); + } + } + + if ( aChangedSettingEnum == MCASettings::EOwnAlias ) + { + // this branch will not get done unless alias usage has been enabled + // through resource variation. + UpdateAliasAttributeL(); + } + + // Presence authorization mode change + if ( aChangedSettingEnum == MCASettings::EAuthorizeIMPresence ) + { + SetPresenceAuthorizationL( iApplicationSettings->Value( + MCASettings::EAuthorizeIMPresence ) ); + } + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::HandleAttributeTransactionError +// Handler for fetcher errors +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::HandleAttributeTransactionError( + TInt aError, + CPEngAttributeTransaction2& /*aTransaction*/, + TInt aTransactionOperation ) + { + if ( aTransactionOperation == EPEngTransOpOwnAttributePublish ) + { + CHAT_DP( D_CHAT_LIT( "CCAPEngPresenceManager::\ + HandlePresencePublishError, error %d" ), aError ); + iRequestQueue.ResponseReceived( TCARequestQueue::EPublisherWait ); + } + else if ( ( aTransactionOperation == EPEngTransOpAttributeFetchToCache ) || + ( aTransactionOperation == EPEngTransOpAttributeFetchToObjects ) ) + { + CHAT_DP( D_CHAT_LIT( "CCAPEngPresenceManager::HandleAttributeFetchError, \ + error = %d" ), aError ); + iRequestQueue.ResponseReceived( TCARequestQueue::EFetcherWait ); + + // delete previous results, so that we don't accidentally use them + if ( aTransactionOperation == EPEngTransOpAttributeFetchToObjects ) + { + iFetchObjects.ResetAndDestroy(); + } + } + + iOperationError = CAPresenceUtils::MapErrorPECtoCSP( aError ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::HandleAttributeTransactionCompleteL +// Handler for fetcher complete +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::HandleAttributeTransactionCompleteL( + MPEngTransactionStatus2& aStatus, + CPEngAttributeTransaction2& aTransaction, + TInt aTransactionOperation ) + { + if ( aTransactionOperation == EPEngTransOpOwnAttributePublish ) + { + CHAT_DP_TXT( "CCAPEngPresenceManager::HandlePresencePublishCompletedL" ); + NotifyOwnPresenceObserverL(); + iRequestQueue.ResponseReceived( TCARequestQueue::EPublisherWait ); + } + else if ( aTransactionOperation == EPEngTransOpAttributeFetchToCache ) + { + CHAT_DP_TXT( "CCAPEngPresenceManager::HandleAttributeFetchCompletedL" ); + iRequestQueue.ResponseReceived( TCARequestQueue::EFetcherWait ); + } + else if ( aTransactionOperation == EPEngTransOpAttributeFetchToObjects ) + { + CHAT_DP_TXT( "CCAPEngPresenceManager::HandleAttributeFetchCompletedL" ); + iFetchObjects.ResetAndDestroy(); + aTransaction.GetFetchedAttributes( iFetchObjects ); + iRequestQueue.ResponseReceived( TCARequestQueue::EFetcherWait ); + } + iOperationError = CAPresenceUtils::MapErrorPECtoCSP( aStatus.Status() ); + CAPresenceUtils::HandleTransactionStatusL( aStatus, *iErrors ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::HandlePresenceChangeL +// Handler for attribute change event +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::HandlePresenceChangeL( + CPEngPresenceNotifier2& /*aNotifier*/, + CPEngTrackedPresenceIDs2& aChangedPresenceIDs ) + { + CHAT_DP_TXT( "CCAPEngPresenceManager::HandlePresenceChangeL" ); + + DecodeNotifierDataL( &aChangedPresenceIDs, NULL ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::HandlePresenceError +// Handler for attribute notifier errors +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::HandlePresenceError( TInt aError, + CPEngPresenceNotifier2& /* aNotifier */ ) + { + CHAT_DP( D_CHAT_LIT( "CCAPEngPresenceManager::HandlePresenceNotifyError: %d" ), + aError ); + + iOperationError = CAPresenceUtils::MapErrorPECtoCSP( aError ); + } + + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::DecodeFetcherDataL +// Decodes fetcher data +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::DecodeFetcherDataL( + const MDesCArray& aUserList, + CDesCArray *aStateOnline, + CDesCArray *aStateOffline, + CDesCArray *aStateUnknown, + TBool aUpdateStorage ) + { + MCAStoredContacts* contacts = aUpdateStorage ? + CCAStorageManagerFactory::ContactListInterfaceL() : NULL; + + User::LeaveIfError( iAttrArrays.Append( TDecodeAttrParams() ) ); + // newly created array entry must be filled completely, so no leaving allowed! + TInt pos( iAttrArrays.Count() - 1 ); + TDecodeAttrParams& decodeParams = iAttrArrays[ pos ]; + decodeParams.iPresenceStates = &iPresenceStates; + decodeParams.iContactStorage = contacts; + decodeParams.iStateOnline = aStateOnline; + decodeParams.iStateOffline = aStateOffline; + decodeParams.iStateUnknown = aStateUnknown; + decodeParams.iEntryIndex = 0; + decodeParams.iServerPrefers = iServerPrefers; + decodeParams.iWait = TCARequestQueue::EDecodeAttrWait; + decodeParams.iWatcherObserver = NULL; + TRAPD( err, PopulateAttrModelsL( decodeParams.iArray, &aUserList ) ); + if ( err != KErrNone ) + { + // array entry could not be filled properly => remove it + decodeParams.iArray.ResetAndDestroy(); + iAttrArrays.Remove( pos ); + // now it's safe to leave + User::Leave( err ); + } + + iOperationError = KErrNone; + + if ( !iIdle->IsActive() ) + { + iIdle->Start( TCallBack( DecodeAttrModels, this ) ); + } + + iRequestQueue.WaitForResponseL( TCARequestQueue::EDecodeAttrWait ); + + User::LeaveIfError( iOperationError ); + } + + +TInt CCAPEngPresenceManager::DecodeAttrModels( TAny *aInstance ) + { + return static_cast( aInstance )-> + DoDecodeAttrModels(); + } + +TInt CCAPEngPresenceManager::DoDecodeAttrModels() + { + CHAT_DP_TXT( "CCAPEngPresenceManager::DoDecodeAttrModels" ); + TBool retval( EFalse ); + + if ( !iAttrArrays.Count() ) // No modelarray to decode. + { + return EFalse; + } + + CHAT_DP( D_CHAT_LIT( "CCAPEngPresenceManager::DoDecodeAttrModels, \ + Count of attr packets %d" ), iAttrArrays.Count() ); + + TDecodeAttrParams& decodeParams = iAttrArrays[ 0 ]; + + TRAP( iOperationError, retval = CAPresenceUtils::DecodeAttrModelsL( + decodeParams ) ); + + if ( iOperationError != KErrNone || !retval ) + { + // Ready. + TCARequestQueue::TWaitCategory wait = decodeParams.iWait; + decodeParams.iArray.ResetAndDestroy(); + iAttrArrays.Remove( 0 ); + if ( wait != TCARequestQueue::ENoWaitNeeded ) + { + iRequestQueue.ResponseReceived( wait ); + } + + if ( iOperationError != KErrNone ) + { + CActiveScheduler::Current()->Error( iOperationError ); + } + } + + return TBool( iAttrArrays.Count() ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::DecodeNotifierDataL +// Decodes notifier data +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::DecodeNotifierDataL( + CPEngTrackedPresenceIDs2* aChangedPresenceIDs, + const MDesCArray* aUserList ) + { + CHAT_DP_TXT( "CCAPEngPresenceManager::DecodeNotifierDataL - Enter" ); + + if ( !aChangedPresenceIDs && aUserList ) + { + return; + } + + MCAStoredContacts* contacts = CCAStorageManagerFactory::ContactListInterfaceL(); + + User::LeaveIfError( iAttrArrays.Append( TDecodeAttrParams() ) ); + // newly created array entry must be filled completely, so no leaving allowed! + TInt pos( iAttrArrays.Count() - 1 ); + TDecodeAttrParams& decodeParams = iAttrArrays[ pos ]; + decodeParams.iPresenceStates = &iPresenceStates; + decodeParams.iContactStorage = contacts; + decodeParams.iStateOnline = NULL; + decodeParams.iStateOffline = NULL; + decodeParams.iStateUnknown = NULL; + decodeParams.iEntryIndex = 0; + decodeParams.iServerPrefers = iServerPrefers; + decodeParams.iWait = TCARequestQueue::ENoWaitNeeded; + decodeParams.iWatcherObserver = iWatcherObserver; + TRAPD( err, PopulateAttrModelsL( decodeParams.iArray, aUserList, aChangedPresenceIDs ) ); + if ( err != KErrNone ) + { + // array entry could not be filled properly => remove it + decodeParams.iArray.ResetAndDestroy(); + iAttrArrays.Remove( pos ); + // now it's safe to leave + User::Leave( err ); + } + + if ( iAttributeProcessing && !iIdle->IsActive() ) + { + iIdle->Start( TCallBack( DecodeAttrModels, this ) ); + } + + CHAT_DP_TXT( "CCAPEngPresenceManager::DecodeNotifierDataL - Done" ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::IsLoggedIn +// Returns the network state of module +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CCAPEngPresenceManager::IsLoggedIn() const + { + return iNetworkState == ELoggedIn ; + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::PopulateAttrModelsL +// Populates attribute-model-array with given data. If aNotifierData is given, +// then uses notifier data, otherwise uses fetcher data +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::PopulateAttrModelsL( + RPointerArray& aArray, + const MDesCArray* aUserList, + CPEngTrackedPresenceIDs2* aChangedPresenceIDs /*=NULL*/ ) + { + CHAT_DP( D_CHAT_LIT( "CCAPEngPresenceManager::PopulateAttrModelsL, \ + &aChangedPresenceIDs=%d" ), aChangedPresenceIDs ); + + if ( !iPEngAPIInitialized ) + { + CHAT_DP_TXT( "iPEngAPIInitialized not initialized" ); + return; + } + + TLinearOrder rule( + CAPresenceUtils::CompareAttrModelArray ); + + if ( aChangedPresenceIDs ) // Notifier + { + // wrap changed ids and update models for those users + TTrackedPresenceIds updatedIds; + updatedIds.InitializeLC( *aChangedPresenceIDs ); + ExtractAttributeModelsForUsersL( updatedIds, aArray ); + CleanupStack::PopAndDestroy(); // updatedIds + } + else // Fetcher + { + // we are using fetcher which has fetched the attributes to cache. + // so we must use the cache to decode the stuff + ExtractAttributeModelsForUsersL( *aUserList, aArray ); + } + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::ExtractAttributeModelL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::ExtractAttributeModelL( const TDesC& aId, + RPointerArray& aArray, TUint32 aAttribute ) + { + MPEngPresenceAttrModel2* attributeModel = NULL; + TInt error( KErrNone ); + if ( aId.Length() == 0 ) + { + // no id + error = iPEngAttributeStore->GetOwnAttribute( aAttribute, + attributeModel ); + } + else + { + // have id + error = iPEngAttributeStore->GetCachedAttribute( aId, aAttribute, + attributeModel ); + } + + if ( error == KErrNone ) + { + CleanupClosePushL( *attributeModel ); + aArray.AppendL( attributeModel ); // ownership transfers + CleanupStack::Pop(); // attributeModel + } + else if ( ( error != KErrNotSupported ) && ( error != KErrNotFound ) ) + { + User::Leave( error ); + } + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::SetPresenceAuthorizationL +// Sets presence authorization mode +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::SetPresenceAuthorizationL( + TInt aAppSettingsAuthValue ) + { + CHAT_DP( D_CHAT_LIT( "CCAPEngPresenceManager::SetPresenceAuthorizationL, \ + aAppSettingsAuthValue = %d" ), aAppSettingsAuthValue ); + + if ( !iPEngAPIInitialized ) + { + iCachedAppSettingsAuthValue = aAppSettingsAuthValue; + return; + } + + if ( iRAUsed ) + { + CHAT_DP_TXT( "CCAPEngPresenceManager::SetPresenceAuthorizationL - \ + Reactive authorization in use, ignoring call" ); + return; + } + + CHAT_DP_TXT( "CCAPEngPresenceManager::SetPresenceAuthorizationL - \ + Reactive authorization not in use" ); + + switch ( aAppSettingsAuthValue ) + { + case MCASettings::EAll: + { + CHAT_DP_TXT( "Own presence publish: to all" ); + iListManager->SetAuthorizationToAllL(); + break; + } + case MCASettings::EFriends: + { + CHAT_DP_TXT( "Own presence publish: to friends" ); + iListManager->SetAuthorizationToFriendsL(); + break; + } + case MCASettings::ENobody: + { + CHAT_DP_TXT( "Own presence publish: to nobody" ); + iListManager->SetAuthorizationToNoneL(); + break; + } + default: + { + User::Leave( KErrNotSupported ); + break; + } + } + } + + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::FetchAttributesL +// Fetches attributes for given users +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::FetchAttributesL( const MDesCArray& aUsers, + CDesCArray *aStateOnline, + CDesCArray *aStateOffline, + CDesCArray *aStateUnknown, + TBool aUpdateStorage ) + { + CHAT_DP_TXT( "CCAPEngPresenceManager::FetchAttributesL" ); + + if ( IsLoggedIn() && aUsers.MdcaCount() > 0 ) + { + CHAT_DP_TXT( "CCAPEngPresenceManager::FetchAttributesL, \ + fetching attributes" ); +#ifdef _DEBUG + TInt count( aUsers.MdcaCount() ); + for ( TInt i( 0 ); i < count; ++i ) + { + TPtrC data( aUsers.MdcaPoint( i ) ); + CHAT_DP( D_CHAT_LIT( "CCAPEngPresenceManager::FetchAttributesL, \ + user %d: %S" ), i, &data ); + } +#endif + iOperationError = KErrNone; + + // Fetching of attributes may return error + // Leave to avoid hanging in WaitResponseL + User::LeaveIfError( iPEngAttributeTransaction-> + FetchAttributesToCache( aUsers, + iAttributes.Array(), + *this ) ); + + iRequestQueue.WaitForResponseL( TCARequestQueue::EFetcherWait ); + CHAT_DP( D_CHAT_LIT( "CCAPEngPresenceManager::FetchAttributesL, \ + attribute fetch done (%d)" ), iOperationError ); + + // Decode retrieved data if we still have memory left + if ( iOperationError != KErrNoMemory && iOperationError != KErrDiskFull ) + { + DecodeFetcherDataL( aUsers, aStateOnline, aStateOffline, + aStateUnknown, aUpdateStorage ); + } + + User::LeaveIfError( iOperationError ); + } + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::UpdateAliasAttributeL +// Update alias attribute to the network. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::UpdateAliasAttributeL() + { + CHAT_DP_TXT( "CCAPEngPresenceManager::UpdateAliasAttributeL" ); + + if ( iNetworkState != ELoggedIn && iNetworkState != ELoggingOut ) + { + CHAT_DP_TXT( "CCAPEngPresenceManager::UpdateAliasAttributeL: No active \ + network state -> ignore!" ); + return; + } + + // check if alias is enabled at all + if ( ! iAliasUsed ) + { + CHAT_DP_TXT( "CCAPEngPresenceManager::UpdateAliasAttributeL: Alias \ + support disabled" ); + return; + } + + HBufC* alias = iApplicationSettings->OwnAliasL(); + if ( !alias ) + { + CHAT_DP_TXT( "CCAPEngPresenceManager::UpdateAliasAttributeL: Alias \ + is not defined" ); + return; + } + + CleanupStack::PushL( alias ); + MPEngPresenceAttrModel2* aliasAttr = NULL; + User::LeaveIfError( iPEngAttributeStore->GetAndLockOwnAttribute( + KUidPrAttrAlias, aliasAttr ) ); + CleanupClosePushL( *aliasAttr ); + aliasAttr->SetDataDesC16L( *alias, EPEngAlias ); + + CHAT_DP_TXT( "CCAPEngPresenceManager::UpdateAliasAttributeL, publishing \ + attribute" ); + iOperationError = KErrNone; + TInt err = iPEngAttributeTransaction->PublishAndUnLockOwnAttribute( + aliasAttr, *this ); + if ( err ) + { + CleanupStack::PopAndDestroy(); // aliasAttr + } + else + { + CleanupStack::Pop( ); // aliasAttr + } + CleanupStack::PopAndDestroy( alias ); + + iRequestQueue.WaitForResponseL( TCARequestQueue::EPublisherWait ); + + CHAT_DP( D_CHAT_LIT( "CCAPEngPresenceManager::UpdateAliasAttributeL, \ + attribute publishing done (%d)" ), iOperationError ); + + if ( iOperationError == ECSPInvalidPresenceValue ) + { + User::Leave( iOperationError ); + } + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::SetReactiveAuthObserver +// Reactive authorization observer for internal events +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::SetReactiveAuthObserver( + MCAReactiveAuthObserver* aRAObserver ) + { + iRAObserver = aRAObserver; + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::CancelPendingRequests +// Fetches attributes for given users +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::CancelPendingRequests() + { + CHAT_DP_FUNC_ENTER( "CancelPendingRequests" ); + + if ( iPEngAttributeTransaction ) + { + iPEngAttributeTransaction->CancelFetchAttributes(); + iPEngAttributeTransaction->CancelPublishOwnAttributes(); + } + + if ( iListManager ) + { + iListManager->CancelPendingRequests(); + } + + CHAT_DP_FUNC_DONE( "CancelPendingRequests" ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::SynchronizePresenceSettingsL +// Make sure server state is in sync with our presence settings +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::SynchronizePresenceSettingsL( + const SServerPrefers& /* aServerPreferences */ ) + { + // authorization + SetPresenceAuthorizationL( iApplicationSettings->Value( + MCASettings::EAuthorizeIMPresence ) ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::AliasL +// Fetch alias for given userid +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +HBufC* CCAPEngPresenceManager::AliasL( const TDesC& aUserId ) + { + if ( aUserId.Length() == 0 ) + { + // can't find alias in this case... + User::Leave( KErrNotFound ); + return NULL; // some compilers demand this + } + HBufC* aliasName = NULL; + + RArray attribute; + CleanupClosePushL( attribute ); + attribute.AppendL( KUidPrAttrAlias ); + + // get alias from network + iOperationError = KErrNone; + + iPEngAttributeTransaction->FetchAttributesToObjects( aUserId, + attribute.Array(), + *this ); + iRequestQueue.WaitForResponseL( TCARequestQueue::EFetcherWait ); + + CHAT_DP( D_CHAT_LIT( "CCAPEngPresenceManager::AliasL, attribute fetch \ + done (%d)" ), iOperationError ); + CleanupStack::PopAndDestroy(); // attribute.Close() + + if ( !iOperationError ) + { + // Fetched attributes are in iFetchObjects + const MPEngPresenceAttrModel2* aliasAttr = + CAPresenceUtils::FindAttr( KUidPrAttrAlias, iFetchObjects ); + + if ( aliasAttr ) + { + // got an alias from the network + TPtrC text = aliasAttr->DataDesC16( EPEngAlias ); + aliasName = text.AllocL(); + } + else + { + // didn't get an alias, so use an empty alias + aliasName = KNullDesC().AllocL(); + } + } + else + { + // got some problem + User::LeaveIfError( iOperationError ); + return NULL; // some compilers demand this + } + + // release fetched attributes + iFetchObjects.ResetAndDestroy(); + + // ownership transfers + return aliasName; + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::AliasL +// Fetch alias for given userid +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +HBufC* CCAPEngPresenceManager::AliasL( MCAStoredContact* aContact ) + { + if ( !aContact ) + { + return NULL; + } + + HBufC* aliasName = AliasL( aContact->UserId() ); + CleanupStack::PushL( aliasName ); + + if ( KErrNone != aContact->Alias().Compare( *aliasName ) ) + { + CCAStorageManagerFactory::ContactListInterfaceL()->ResortContactInAll( aContact ); + aContact->SetAliasL( *aliasName ); + aContact->SignalChanges(); + } + + CleanupStack::Pop( aliasName ); + + // ownership transfers + return aliasName; + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::ChangeStatusL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CCAPEngPresenceManager::ChangeStatusL( TPresenceStatus aStatus, + const TDesC& aStatusMessage ) + { + CHAT_DP_FUNC_ENTER( "ChangeStatusL" ); + + if ( !iPEngAPIInitialized ) + { + // cache the status + iCachedPresenceStatus = aStatus; + HBufC* tempStatusText = aStatusMessage.AllocL(); + delete iCachedStatusText; + iCachedStatusText = tempStatusText; + iCachedStatus = ETrue; + return KErrNone; + } + + RPointerArray models; + CleanupStack::PushL( TCleanupItem( CAPresenceUtils::DestroyCloseModelArray, &models ) ); + + CCAState* state = CAPresenceUtils::FindStateL( aStatus, iOwnStates ); + + if ( state ) + { + TInt attrCount( state->iAttributes.Count() ); + for ( TInt i( 0 ); i < attrCount; ++i ) + { + TCAAttribute& attr = state->iAttributes[i]; + MPEngPresenceAttrModel2* pengAttr = NULL; + User::LeaveIfError( iPEngAttributeStore->GetAndLockOwnAttribute( + attr.iAttribute, pengAttr ) ); + CleanupClosePushL( *pengAttr ); + + if ( attr.iAttribute == KUidPrAttrStatusText ) + { + // special case, set the status text + pengAttr->SetDataDesC16L( aStatusMessage, EPEngStatusText ); + } + else + { + // otherwise set the value from list + pengAttr->SetDataIntL( attr.iData, attr.iField, attr.iGroup ); + } + + // set qualifier and append to list + pengAttr->SetQualifier( attr.iQualifier ); + models.AppendL( pengAttr ); + CleanupStack::Pop(); // pengAttr + } + } + +#ifdef _DEBUG + else + { + CHAT_DP_TXT( "!!UI offered presence state that was not defined in resource!!" ); + } +#endif // _DEBUG + + iOperationError = KErrNone; + if ( models.Count() > 0 ) + { + // we have some attributes, publish them + CHAT_DP_TXT( "CCAPEngPresenceManager::ChangeStatusL, publishing attributes" ); + User::LeaveIfError( iPEngAttributeTransaction->PublishAndUnLockOwnAttributes( + models, + *this ) ); + CleanupStack::Pop(); // models + + iRequestQueue.WaitForResponseL( TCARequestQueue::EPublisherWait ); + CHAT_DP( D_CHAT_LIT( "CCAPEngPresenceManager::ChangeStatusL, attribute \ + publishing done (%d)" ), iOperationError ); + } + else + { + CleanupStack::PopAndDestroy(); // models + } + + CHAT_DP_FUNC_DONE( "ChangeStatusL" ); + return iOperationError; + } + + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::ChangeStatusMessageL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CCAPEngPresenceManager::ChangeStatusMessageL( const TDesC& aStatusMessage ) + { + CHAT_DP_FUNC_ENTER( "ChangeStatusMessageL" ); + + if ( !iPEngAPIInitialized ) + { + // cache the status text + HBufC* tempText = aStatusMessage.AllocL(); + delete iCachedStatusText; + iCachedStatusText = tempText; + return KErrNone; + } + + MPEngPresenceAttrModel2* statusMessage = NULL; + User::LeaveIfError( iPEngAttributeStore->GetAndLockOwnAttribute( + KUidPrAttrStatusText, statusMessage ) ); + CleanupStack::PushL( statusMessage ); + + statusMessage->SetDataDesC16L( aStatusMessage, EPEngStatusText ); + statusMessage->SetQualifier( ETrue ); + CHAT_DP_TXT( "CCAPEngPresenceManager::ChangeStatusMessageL, publishing \ + attributes" ); + iOperationError = KErrNone; + iPEngAttributeTransaction->PublishAndUnLockOwnAttribute( statusMessage, + *this ); + CleanupStack::Pop( ); // statusMessage + iRequestQueue.WaitForResponseL( TCARequestQueue::EPublisherWait ); + CHAT_DP( D_CHAT_LIT( "CCAPEngPresenceManager::ChangeStatusMessageL, \ + attribute publishing done (%d)" ), iOperationError ); + + CHAT_DP_FUNC_DONE( "ChangeStatusMessageL" ); + return iOperationError; + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::StatusL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +MCAPresence::TPresenceStatus CCAPEngPresenceManager::StatusL() + { + CHAT_DP_FUNC_ENTER( "StatusL" ); + MCAPresence::TPresenceStatus currentStatus( MCAPresence::EOffline ); + + if ( !iPEngAPIInitialized ) + { + // if the api is not initialized -> we are offline + return currentStatus; + } + + RPointerArray attributes; + CAPresenceUtils::PushModelArrayL( attributes, ETrue ); + + MPEngPresenceAttrModel2* userAvailability = NULL; + User::LeaveIfError( iPEngAttributeStore->GetOwnAttribute( + KUidPrAttrUserAvailability, userAvailability ) ); + CleanupClosePushL( *userAvailability ); + attributes.AppendL( userAvailability ); + CleanupStack::Pop(); // userAvailability + + MPEngPresenceAttrModel2* commCap = NULL; + User::LeaveIfError( iPEngAttributeStore->GetOwnAttribute( + KUidPrAttrCommCap, commCap ) ); + CleanupClosePushL( *commCap ); + attributes.AppendL( commCap ); + CleanupStack::Pop(); // commCap + + MPEngPresenceAttrModel2* onlineStatus = NULL; + User::LeaveIfError( iPEngAttributeStore->GetOwnAttribute( + KUidPrAttrOnlineStatus, onlineStatus ) ); + CleanupClosePushL( *onlineStatus ); + attributes.AppendL( onlineStatus ); + CleanupStack::Pop(); // onlineStatus + + MPEngPresenceAttrModel2* clientInfo = NULL; + User::LeaveIfError( iPEngAttributeStore->GetOwnAttribute( + KUidPrAttrClientInfo, clientInfo ) ); + CleanupClosePushL( *clientInfo ); + attributes.AppendL( clientInfo ); + CleanupStack::Pop(); // clientInfo + + currentStatus = + CAPresenceUtils::DecodeOnlineState( + iPresenceStates, attributes ); + + CleanupStack::PopAndDestroy(); // attributes + + CHAT_DP_FUNC_DONE( "StatusL" ); + return currentStatus; + } + + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::AddOwnPresenceStatusObserver +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::AddOwnPresenceStatusObserverL( + MCAPresenceObserver* aObserver ) + { + iOwnStatusObserver = aObserver; + if ( !iSessionSlotID ) + { + // we are not yet online so we queue this observer + iObserverQueued = ETrue; + return; + } + InitializeOwnPresenceObserverL(); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::InitializeOwnPresenceObserverL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::InitializeOwnPresenceObserverL() + { + if ( !iObserverQueued ) + { + // no queued observer, no need to do anything + return; + } + // we don't have to use a temp variable since this + // notifier has to be always created and if creating fails we cannot + // use the old notifier + + if ( iOwnPresenceNotifier ) + { + iOwnPresenceNotifier->RemoveObserver( *this ); + } + + delete iOwnPresenceNotifier; + iOwnPresenceNotifier = NULL; + + iOwnPresenceNotifier = CPEngPresenceNotifier2::NewL( *iSessionSlotID ); + iOwnPresenceNotifier->AddObserver( *this ); + + CArrayFixFlat* observedAttributes = + new CArrayFixFlat( iAttributes.Count() ); // N observed attributes + CleanupStack::PushL( observedAttributes ); + + // just add all attributes to be observed + for ( TInt i = iAttributes.Count() - 1; i >= 0; i-- ) + { + observedAttributes->AppendL( iAttributes[ i ] ); + } + iOwnPresenceNotifier->Start( KPEngUserOwnPresenceId(), + observedAttributes->Array() ); + + CleanupStack::PopAndDestroy( observedAttributes ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::NotifyOwnPresenceObserver +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::NotifyOwnPresenceObserverL() + { + TPresenceStatus status = StatusL(); + TStorageManagerGlobals::TPresenceStatus storageStatus; + switch ( status ) + { + case MCAPresence::EOnline: + { + storageStatus = TStorageManagerGlobals::EOnline; + break; + } + case MCAPresence::EAway: + { + storageStatus = TStorageManagerGlobals::EAway; + break; + } + case MCAPresence::EBusy: + { + storageStatus = TStorageManagerGlobals::EBusy; + break; + } + case MCAPresence::EOffline: // Flowthrough + default: + { + // If we're online, offline means invisible + storageStatus = IsLoggedIn() ? + TStorageManagerGlobals::EInvisible : + TStorageManagerGlobals::EOffline; + break; + } + } + + if ( iPEngAttributeStore ) + { + // Get own status message + MPEngPresenceAttrModel2* statusMessage = NULL; + + TInt err = iPEngAttributeStore->GetOwnAttribute( + KUidPrAttrStatusText, statusMessage ); + CleanupClosePushL( *statusMessage ); + + TPtrC16 statusText( KNullDesC ); + if ( err == KErrNone && statusMessage ) + { + statusText.Set( statusMessage->DataDesC16( EPEngStatusText ) ); + } + + // Update own status + MCAStoredContact& ownStatus = + CCAStorageManagerFactory::ContactListInterfaceL()->OwnStatus(); + + ownStatus.SetOnlineStatus( storageStatus ); + ownStatus.SetStatusTextL( statusText ); + CleanupStack::PopAndDestroy( statusMessage ); // now we can delete this + + ownStatus.SignalChanges(); + } + + if ( iOwnStatusObserver ) + { + // notify observer with current status + iOwnStatusObserver->HandleOwnStatusChange( status ); + } + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::NotifyOwnPresenceObserver +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::InitializePresenceAPIL( + CPEngNWSessionSlotID2& aSessionSlotID ) + { + delete iSessionSlotID; + iSessionSlotID = NULL; + iSessionSlotID = aSessionSlotID.CloneL(); + + InitializePEngAPIL(); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::AddAttributeL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::AddAttributeL( TInt aAttribute ) + { + // add attribute to the end of the attribute list + iAttributes.Append( InternalToPECAttrL( + ( MCAPresence::TDynamicAttributes ) aAttribute ) ); + + // restart the notifier, if any + iListManager->ReplaceAttributesL( iAttributes ); + + // next time something is done, the attributes should be updated + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::RemoveAttributeL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::RemoveAttributeL( TInt aAttribute ) + { + // remove attribute from the attribute list + TUint32 pecAttr = + InternalToPECAttrL( ( MCAPresence::TDynamicAttributes ) aAttribute ); + for ( TInt i = iAttributes.Count() - 1; i >= 0; i-- ) + { + if ( iAttributes[ i ] == pecAttr ) + { + iAttributes.Remove( i ); + } + } + + // restart the notifier, if any + iAttributes.Compress(); + iListManager->ReplaceAttributesL( iAttributes ); + + // next time something is done, the attributes should be updated + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::ResetAttributesL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::ResetAttributesL( + TBool aNotifyListManager /* = ETrue */ ) + { + // always supported list of "base attributes", + // dynamically branded attributes are not to be added here + iAttributes.Reset(); + User::LeaveIfError( iAttributes.Append( KUidPrAttrOnlineStatus ) ); + User::LeaveIfError( iAttributes.Append( KUidPrAttrCommCap ) ); + User::LeaveIfError( iAttributes.Append( KUidPrAttrUserAvailability ) ); + User::LeaveIfError( iAttributes.Append( KUidPrAttrStatusText ) ); + User::LeaveIfError( iAttributes.Append( KUidPrAttrClientInfo ) ); + + if ( aNotifyListManager ) + { + iListManager->ReplaceAttributesL( iAttributes ); + } + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::InternalToPECAttrL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint32 CCAPEngPresenceManager::InternalToPECAttrL( + TDynamicAttributes aAttribute ) + { + switch ( aAttribute ) + { + case EAliasAttr : + { + return KUidPrAttrAlias; + } + default : + { + User::Leave( KErrNotFound ); + break; + } + } + // this is never reached + return 0; + } + +// reactive authorization things +// +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::HandlePendingAuthorizationReqL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::HandlePendingAuthorizationReqL( + CPEngReactAuthNotifier& /* aNotifier */, + TArray< MPEngAuthorizationRequest* >& aPendingAuthReqs ) + { + CHAT_DP_FUNC_ENTER( "HandlePendingAuthorizationReqL" ); + + if ( aPendingAuthReqs.Count() ) + { + iRAObserver->HandleRAPendingReqL(); + } + + CHAT_DP_FUNC_DONE( "HandlePendingAuthorizationReqL" ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::HandlerAuthorizationStatusL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::HandlerAuthorizationStatusL( + CPEngReactAuthNotifier& /* aNotifier */, + TArray< const MPEngAuthorizationStatus* > /*aAuthStatuses*/ ) + { + CHAT_DP_FUNC_ENTER( "HandlerAuthorizationStatusL" ); + + // will be done only once, since the observer will + // ask for all of the requests once it's called. + iRAObserver->HandleRAStatusL(); + + CHAT_DP_FUNC_DONE( "HandlerAuthorizationStatusL" ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::HandleRAError +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::HandleReactAuthError( + TInt aError, + CPEngReactAuthNotifier& /* aNotifier */ ) + { + CHAT_DP_FUNC_ENTER( "HandleReactAuthError" ); + + iRAObserver->HandleRAError( aError ); + + CHAT_DP_FUNC_DONE( "HandleReactAuthError" ); + } + +// reactive authorization transactions + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::HandleReactAuthTransactionCompleteL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::HandleReactAuthTransactionCompleteL( + MPEngTransactionStatus2& /* aStatus */, + CPEngReactAuthTransaction& /* aTransaction */, + TInt /* aTransactionOperation */ ) + { + CHAT_DP_FUNC_ENTER( "HandleReactAuthTransactionCompleteL" ); + + iRequestQueue.ResponseReceived( TCARequestQueue::EReactiveAuthWait ); + + CHAT_DP_FUNC_DONE( "HandleReactAuthTransactionCompleteL" ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::HandleReactAuthTransactionError +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::HandleReactAuthTransactionError( + TInt /* aError */, + CPEngReactAuthTransaction& /* aTransaction */, + TInt /* aTransactionOperation */ ) + { + CHAT_DP_FUNC_ENTER( "HandleReactAuthTransactionError" ); + + iRequestQueue.ResponseReceived( TCARequestQueue::EReactiveAuthWait ); + + CHAT_DP_FUNC_DONE( "HandleReactAuthTransactionError" ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::UpdatePresenceL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::UpdatePresenceL( const TDesC& aUserId ) + { + TOneDesWrapper wvId( aUserId ); + DecodeFetcherDataL( wvId, NULL, NULL, NULL, ETrue ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::ExtractAttributeModelsForUserL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::ExtractAttributeModelsForUserL( + const TDesC& aUserId, + RPointerArray& aAttrModels ) + { + // the base attribute set + ExtractAttributeModelL( aUserId, aAttrModels, KUidPrAttrOnlineStatus ); + + ExtractAttributeModelL( aUserId, aAttrModels, KUidPrAttrCommCap ); + + ExtractAttributeModelL( aUserId, aAttrModels, KUidPrAttrUserAvailability ); + + ExtractAttributeModelL( aUserId, aAttrModels, KUidPrAttrStatusText ); + + ExtractAttributeModelL( aUserId, aAttrModels, KUidPrAttrClientInfo ); + + // add more dynamically branded attributes here + if ( iAliasUsed ) + { + ExtractAttributeModelL( aUserId, aAttrModels, KUidPrAttrAlias ); + } + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::PresenceStates +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +const RPointerArray& CCAPEngPresenceManager::PresenceStates() + { + return iPresenceStates; + } + +void CCAPEngPresenceManager::SetAttributeProcessing( TBool aEnabled ) + { + iAttributeProcessing = aEnabled; + if ( iAttributeProcessing ) + { + if ( iAttrArrays.Count() && !iIdle->IsActive() ) + { + // we have something to process + iIdle->Start( TCallBack( DecodeAttrModels, this ) ); + } + } + else + { + if ( iIdle->IsActive() ) + { + // we had something ongoing, so pause it + iIdle->Cancel(); + } + } + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::AllowReactiveAuthRequestL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::SendReactiveAuthResponseL( TInt aId, + TBool aResponse ) + { + CHAT_DP_FUNC_ENTER( "SendReactiveAuthResponseL" ); + + MPEngAuthorizationRequest& authReq = + iRAStore->PendingAuthorizationReq( aId ); + + // lock the response so nobody else will mess with it + MPEngAuthorizationRespond* response = NULL; + iRAStore->GetAndLockAuthorizationRespond( response ); + CleanupClosePushL( *response ); + + if ( aResponse ) + { + // accepted + TArray attr = iAttributes.Array(); + TInt ignore; + TRAP( ignore, authReq.SetAuthorizedAttributesL( attr ) ); + } + else + { + // rejected + TInt ignore; + TRAP( ignore, authReq.DenyAuthorizationL() ); + } + + // now we can publish it. PEC engine knows which one we just changed + if ( KErrNone != + iRATransaction->PublishReactAuthResponds( response, *this ) ) + { + // got error, the lock stays with us + CleanupStack::PopAndDestroy(); // response + } + else + { + iRequestQueue.WaitForResponseL( TCARequestQueue::EReactiveAuthWait ); + CleanupStack::Pop(); // response + // all done, unlocking happens by the store as it took ownership + } + + CHAT_DP_FUNC_DONE( "SendReactiveAuthResponseL" ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::GetNextPendingRARequestL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CCAPEngPresenceManager::GetNextPendingRARequestL( TInt& aId, + TDes& aUserId, + TInt& aLastPos ) + { + CHAT_DP_FUNC_ENTER( "GetNextPendingRARequestL" ); + TInt count = iRAStore->PendingAuthorizationReqCount(); + for ( TInt i( 0 ) ; i < count ; ++i ) + { + MPEngAuthorizationRequest& authReq = + iRAStore->PendingAuthorizationReq( i ); + + if ( MPEngAuthorizationRequest::EPEngAuthPending == + authReq.AuthorizationState() ) + { + // found a pending one + + // caller is interested in these + aId = i; + aUserId.Copy( authReq.UserId() ); + aLastPos = i + 1; + CHAT_DP_FUNC_DONE( "GetNextPendingRARequestL" ); + return ETrue; + } + } + return EFalse; + /* + + if ( ( count > 0 ) && ( aLastPos < ( count-1 ) ) ) + { + // take the first pending one from the queue for processing, + // find out which one it is. + TBool getOut = EFalse; + + // for ( TInt i = 0; ! getOut && ( i < count ); i++ ) + // queue even after it's responded! + for ( i = aLastPos; ! getOut && ( i < count ); i++ ) + { + MPEngAuthorizationRequest& authReq = + iRAStore->PendingAuthorizationReq( i ); + + if ( MPEngAuthorizationRequest::EPEngAuthPending == + authReq.AuthorizationState() ) + { + // found a pending one + + // caller is interested in these + aId = i; + aUserId.Copy( authReq.UserId() ); + aLastPos = i; + CHAT_DP_FUNC_DONE("GetNextPendingRARequestL"); + return ETrue; + } + } + aLastPos = i; + retVal = EFalse; + } + else + { + // nothing in queue + retVal = EFalse; + } + + CHAT_DP_FUNC_DONE("GetNextPendingRARequestL"); + return retVal; + */ + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::GetNextRAStatusL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CCAPEngPresenceManager::GetNextRAStatusL( TInt& aId, TBool& aStatus, + TDes& aUserId, TInt& aLastPos ) + { + CHAT_DP_FUNC_ENTER( "GetNextRAStatusL" ); + + TBool retVal = EFalse; + + TInt count = iRAStore->RespondedAuthorizationCount(); + + if ( ( count > 0 ) && ( aLastPos < ( count - 1 ) ) ) + { + // take the next from the queue + aLastPos++; + + const MPEngAuthorizationStatus& authStatus = + iRAStore->RespondedAuthorization( aLastPos ); + + // caller is interested in these + aId = aLastPos; + aStatus = authStatus.AuthorizationStatus() == + MPEngAuthorizationStatus::EPEngAuthAccepted; + aUserId.Copy( authStatus.UserId() ); + + // stuff left in queue? + retVal = aLastPos < ( iRAStore->RespondedAuthorizationCount() - 1 ) + ? ETrue : EFalse; + } + else + { + // nothing in queue + retVal = EFalse; + } + + CHAT_DP_FUNC_DONE( "GetNextRAStatusL" ); + return retVal; + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::PendingRARequestCount +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CCAPEngPresenceManager::PendingRARequestCount() + { + CHAT_DP_FUNC_ENTER( "PendingRARequestCount" ); + TInt count = iRAStore->PendingAuthorizationReqCount(); + CHAT_DP_FUNC_DONE( "PendingRARequestCount" ); + return count; + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::RAStatusCount +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CCAPEngPresenceManager::RAStatusCount() + { + CHAT_DP_FUNC_ENTER( "RAStatusCount" ); + TInt count = iRAStore->RespondedAuthorizationCount(); + CHAT_DP_FUNC_DONE( "RAStatusCount" ); + return count; + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::PostLoginRAFlushL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::PostLoginRAFlushL() + { + CHAT_DP_FUNC_ENTER( "PostLoginRAFlushL" ); + + // handle any reactive authorization events which came during login, + // when IM Presence was not listening yet + + // start the RA notifier + if ( !iRANotifier->IsActive() ) + { + iRANotifier->Start(); + } + + if ( iRAStore->PendingAuthorizationReqCount() ) + { + // pending authorization requests + iRAObserver->HandleRAPendingReqL(); + } + + if ( iRAStore->RespondedAuthorizationCount() ) + { + // incoming status stuff + iRAObserver->HandleRAStatusL(); + } + + CHAT_DP_FUNC_DONE( "PostLoginRAFlushL" ); + } + +// ----------------------------------------------------------------------------- +// CCAPEngPresenceManager::ExtractAttributeModelsForUsersL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CCAPEngPresenceManager::ExtractAttributeModelsForUsersL( + const MDesCArray& aUserList, + RPointerArray& aAttrModels ) + { + CHAT_DP_FUNC_ENTER( "ExtractAttributeModelsForUsersL" ); + + TInt count = aUserList.MdcaCount(); + for ( TInt i = 0 ; i < count; ++i ) + { + // the base attribute set + ExtractAttributeModelL( aUserList.MdcaPoint( i ), aAttrModels, + KUidPrAttrOnlineStatus ); + ExtractAttributeModelL( aUserList.MdcaPoint( i ), aAttrModels, + KUidPrAttrCommCap ); + ExtractAttributeModelL( aUserList.MdcaPoint( i ), aAttrModels, + KUidPrAttrUserAvailability ); + ExtractAttributeModelL( aUserList.MdcaPoint( i ), aAttrModels, + KUidPrAttrStatusText ); + ExtractAttributeModelL( aUserList.MdcaPoint( i ), aAttrModels, + KUidPrAttrClientInfo ); + + // add more dynamically branded attributes here + if ( iAliasUsed ) + { + ExtractAttributeModelL( aUserList.MdcaPoint( i ), aAttrModels, + KUidPrAttrAlias ); + } + } + + CHAT_DP_FUNC_DONE( "ExtractAttributeModelsForUsersL" ); + } + +// End of File