diff -r 000000000000 -r 094583676ce7 wvuing/wvuieng/EngSrc/CCAInviteManager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wvuing/wvuieng/EngSrc/CCAInviteManager.cpp Thu Dec 17 08:41:52 2009 +0200 @@ -0,0 +1,692 @@ +/* +* Copyright (c) 2003-2005 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: Handles incoming invitations +* +*/ + + +// INCLUDE FILES +#include "PrivateEngineDefinitions.h" +#include "PublicEngineDefinitions.h" +#include "CCAInviteManager.h" // Own header +#include "MCAInviteObserver.h" // Observer interface +#include "MCASettings.h" // Internal settings +#include "ChatDebugPrint.h" // For debug macros +#include "CCARequestMapper.h" +#include "CCAInviteTracker.h" +#include "CCAStoragemanagerFactory.h" +#include "CCAInvitation.h" + +#include "MCAStoredContacts.h" +#include "MCAStoredGroup.h" +#include "MCAStoredGroups.h" +#include "MCAGroupManagerInterface.h" +#include "MCAExtendedStoredGroup.h" +#include "MCAGroupOperations.h" + +#include "MCAImpsFactory.h" + +#include "ChatDebugAssert.h" + +#include + +// CONSTANTS +const TInt KMaxIDNumberLength = 5; //also used in ChatDefinitions. +//both must be synchronous + +_LIT( KInviteFormatString, "%d" ); + +// ================= MEMBER FUNCTIONS ======================= + +// Symbian OS default constructor can leave. +void CCAInviteManager::ConstructL() + { + iRejectReason = HBufC::NewL( KMaxRejectReasonLength ); + iImpsFundAPI = iImpsFactory->CreateFundClientL(); + } + +// Two-phased constructor. +CCAInviteManager* CCAInviteManager::NewL( + MCAImpsFactory* aIMPSFactory, + MCASettings& aSettingsAPI, + CCARequestMapper& aRequestMapper, + MCAGroupManagerInterface& aGroupManager ) + { + CCAInviteManager* self = new ( ELeave ) CCAInviteManager( + aIMPSFactory, + aSettingsAPI, + aRequestMapper, + aGroupManager ); + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + return self; + } + +// Destructor +CCAInviteManager::~CCAInviteManager() + { + iInviteTrackerQueue.ResetAndDestroy(); + iInviteTrackerQueue.Close(); + + iInviteObservers.Close(); + delete iLastInviteId; + delete iRejectReason; + } + +// C++ default constructor can NOT contain any code, that +// might leave. +// +CCAInviteManager::CCAInviteManager( + MCAImpsFactory* aIMPSFactory, + MCASettings& aSettingsAPI, + CCARequestMapper& aRequestMapper, + MCAGroupManagerInterface& aGroupManager ) : + iRequestMapper( &aRequestMapper ), + iSettingsAPI( aSettingsAPI ), + iImpsFactory( aIMPSFactory ), + iGroupManager( &aGroupManager ) + { + } + +// --------------------------------------------------------- +// CCAInviteManager::InviteExpired +// (other items were commented in a header). +// --------------------------------------------------------- +// +void CCAInviteManager::InviteExpiredL( const MCAInvitation* aInvitation ) + { + CHAT_DP_TXT( "CCAInviteManager::InviteExpiredL" ); + + // signal observers + TInt count( iInviteObservers.Count() ); + for ( TInt i( 0 ); i < count; i++ ) + { + if ( iInviteObservers[ i ] ) + { + // it's a non-NULL + iInviteObservers[ i ]->HandleInvitationEventL( + MCAInviteObserver::EInviteExpired, aInvitation ); + } + } + + RemoveInviteL( aInvitation ); + } + + +// --------------------------------------------------------- +// CCAInviteManager::AddInviteObserver +// (other items were commented in a header). +// --------------------------------------------------------- +// +TInt CCAInviteManager::AddInviteObserver( MCAInviteObserver* aObserver ) + { + return iInviteObservers.Append( aObserver ); + } + + +// --------------------------------------------------------- +// CCAInviteManager::RemoveInviteObserver +// (other items were commented in a header). +// --------------------------------------------------------- +// +void CCAInviteManager::RemoveInviteObserver( MCAInviteObserver* aObserver ) + { + TInt pos( iInviteObservers.Find( aObserver ) ); + if ( pos != KErrNotFound ) + { + iInviteObservers.Remove( pos ); + iInviteObservers.Compress(); + } + } + + +// --------------------------------------------------------- +// CCAInviteManager::SendInvitationL +// (other items were commented in a header). +// --------------------------------------------------------- +// +void CCAInviteManager::SendInvitationL( + const CCAInvitationRequest& aInvitation ) + { + CHAT_DP( D_CHAT_LIT( "Sending invite to group %S" ), &aInvitation.GroupID() ); + + PrepareGroupForInviteeL( aInvitation ); + + HBufC* loggedUser = iSettingsAPI.ValueL( MCASettings::EOwnWVUserID ); + CleanupStack::PushL( loggedUser ); + + HBufC* idTemplate = loggedUser->ReAllocL( loggedUser->Length() + + KMaxIDNumberLength ); + CleanupStack::Pop( loggedUser ); + + TPtr idPtr( idTemplate->Des() ); + idPtr.Append( KInviteFormatString ); + + CleanupStack::PushL( idTemplate ); + + iLastInviteId = HBufC::NewL( idTemplate->Length() ); + TPtr generatedIDPtr( iLastInviteId->Des() ); + generatedIDPtr.Format( *idTemplate, iInviteIDOrdinal++ ); + + iCurrentInviteRequest = &aInvitation; + + CHAT_DP( D_CHAT_LIT( "Sending invite: id=%S" ), iLastInviteId ); + + iCurrentOpId = iImpsFundAPI->InviteGroupRequestL( + *iLastInviteId, // Invite ID + &aInvitation.Invitees(), // Invited user IDs + NULL, // Screen names + NULL, // Group names + aInvitation.GroupID(), // Group + KNullDesC, // Own screenname + KNullDesC, // Owns groupname + aInvitation.Message(), // Invite message + aInvitation.Timeout() ); // Validity period + + CCARequest* request = iRequestMapper->CreateRequestL( iCurrentOpId ); // CSI: 35 # Ownership is not transferred to caller. + + delete iLastInviteId; + iLastInviteId = NULL; + iCurrentInviteRequest = NULL; + + iRequestMapper->RemoveRequestAndLeaveIfErrorL( request ); + + CleanupStack::PopAndDestroy( idTemplate ); + } + + +// --------------------------------------------------------- +// CCAInviteManager::PopulateInviteList +// (other items were commented in a header). +// --------------------------------------------------------- +// +void CCAInviteManager::PopulateInviteList( + RPointerArray< MCAInvitation >& aList ) + { + aList.Reset(); + TInt count( iInviteTrackerQueue.Count() - 1 ); + // populate the list backwards so that the most recently received + // invitation gets the first slot in the list + for ( ; count >= 0; count-- ) + { + // the error codes can be ignored, because it's not so fatal + // if one invitation is missing from the list. + // The other methods in UI will fail in any case. + aList.Append( iInviteTrackerQueue[ count ]->Invitation() ); + } + } + + +// --------------------------------------------------------- +// CCAInviteManager::ActiveInvitations +// (other items were commented in a header). +// --------------------------------------------------------- +// +TInt CCAInviteManager::ActiveInvitations() + { + return iInviteTrackerQueue.Count(); + } + + +// --------------------------------------------------------- +// CCAInviteManager::RemoveInvitation +// (other items were commented in a header). +// --------------------------------------------------------- +// +void CCAInviteManager::RemoveInvitationL( MCAInvitation* aInvitation ) + { + RemoveInviteL( aInvitation ); + } + + +// --------------------------------------------------------- +// CCAInviteManager::RejectReasonPtr +// (other items were commented in a header). +// --------------------------------------------------------- +// +HBufC* CCAInviteManager::RejectReasonPtr() + { + return iRejectReason; + } + +// --------------------------------------------------------- +// CCAInviteManager::UnreadInvitesCount +// (other items were commented in a header). +// --------------------------------------------------------- +// +TInt CCAInviteManager::UnreadInvitesCount() const + { + TInt inviteCount( iInviteTrackerQueue.Count() ); + TInt unreadCount( 0 ); + for ( TInt i( 0 ); i < inviteCount; i++ ) + { + if ( !iInviteTrackerQueue[ i ]->Invitation()->IsRead() ) + { + ++unreadCount; + } + } + return unreadCount; + } + +// --------------------------------------------------------- +// CCAInviteManager::HandleGroupInviteL +// (other items were commented in a header). +// --------------------------------------------------------- +// +void CCAInviteManager::HandleGroupInviteL( const TDesC& aInviteID, + const TDesC& aUserID, + const TDesC& aScreenName, + const TDesC& aGroupName, + const TDesC& aInviteReason, + const TInt aValidityPeriod, + TImpsCspIdentifier& /* aCspId */ ) + { + CHAT_DP_TXT( "Received new invitation!" ); + CHAT_DP( D_CHAT_LIT( " * %S invites us to group: %S" ), + &aUserID, &aGroupName ); + + MCAStoredContacts* contactList = NULL; + + TRAPD( err, contactList = + CCAStorageManagerFactory::ContactListInterfaceL() ); + if ( ( err != KErrNone ) || ( ! contactList ) ) + { + // we can't leave, but we can return + CHAT_DP_TXT( "CCAInviteManager::GroupInviteUserRequest - Couldn't \ + get contactlist interface" ); + return; + } + + // check if the invitation should be blocked + TInt receiveInvitations( iSettingsAPI.Value( + MCASettings::EReceiveInvitations ) ); + if ( receiveInvitations == MCASettings::ENobody ) + { + // ignore invites from everyone + CHAT_DP_TXT( " * invitations blocked from everyone" ); + return; + } + else if ( receiveInvitations == MCASettings::EFriends && + ( ! contactList->FindAnyContact( aUserID ) ) ) + { + // invite sender not found from friends list, ignore invite + CHAT_DP_TXT( " * invitations blocked from everyone except friends" ); + return; + } + + // ok, the invitation should be processed + MCAInvitation* invitation = NULL; + err = KErrNone; + TRAP( err, invitation = CreateInviteRequestL( aInviteID, + aUserID, + aScreenName, + aGroupName, + aInviteReason, + aValidityPeriod ) ); + + if ( err != KErrNone ) + { + return; + } + + CHAT_DP_TXT( " * invitation created" ); + + // create a invitetracker that takes care of expiring the invite + CCAInviteTracker* trackedInvite = NULL; + err = KErrNone; + TRAP( err, trackedInvite = CCAInviteTracker::NewL( this, invitation ) ); + + if ( err != KErrNone ) + { + delete invitation; + return; + } + + // append the invite to the list + if ( iInviteTrackerQueue.Append( trackedInvite ) != KErrNone ) + { + delete trackedInvite; + return; + } + + CHAT_DP_TXT( " * signalling observers" ); + // signal observers + TInt count( iInviteObservers.Count() ); + for ( TInt i( 0 ); i < count; i++ ) + { + if ( iInviteObservers[ i ] ) + { + // it's non-NULL + iInviteObservers[ i ]->HandleInvitationEventL( + MCAInviteObserver::ENewInvite, invitation ); + } + } + + } + +// --------------------------------------------------------- +// CCAInviteManager::ReplyInvitationL +// (other items were commented in a header). +// --------------------------------------------------------- +// +void CCAInviteManager::HandleImInviteL( const TDesC& /* aInviteID */, + const TDesC& /* aUserID */, + const TDesC& /* aInviteReason */, + const TInt /* aValidityPeriod */, + TImpsCspIdentifier& /* aCspId */ ) + { + __CHAT_ASSERT_DEBUG( EFalse ); + } + +// --------------------------------------------------------- +// CCAInviteManager::ReplyInvitationL +// (other items were commented in a header). +// --------------------------------------------------------- +// +void CCAInviteManager::HandleContentInviteL( const TDesC& /* aInviteID */, + const TDesC& /* aUserID */, + MDesCArray* /* aUrlList */, + const TDesC& /* aInviteReason */, + const TInt /* aValidityPeriod */, + TImpsCspIdentifier& /* aCspId */ ) + { + __CHAT_ASSERT_DEBUG( EFalse ); + } + +// --------------------------------------------------------- +// CCAInviteManager::ReplyInvitationL +// (other items were commented in a header). +// --------------------------------------------------------- +// +void CCAInviteManager::ReplyInvitationL( const MCAInvitation* aInvitation, + const TBool aInviteAccepted, + const TDesC& aResponse, + const TDesC& aScreenName + ) + { + CHAT_DP_TXT( "Reply to invite" ); + + CCARequest* request = iRequestMapper->CreateRequestL( + iImpsFundAPI->GroupInviteUserResponseL( aInvitation->InviteID(), + aInviteAccepted, + aResponse, + aScreenName, + aInvitation->GroupId() ) ); + + iRequestMapper->RemoveRequest( request ); + + RemoveInviteL( aInvitation ); + } + + +// --------------------------------------------------------- +// CCAInviteManager::HandleInviteResponseL +// (other items were commented in a header). +// --------------------------------------------------------- +// +void CCAInviteManager::HandleInviteResponseL( const TDesC& /* aInviteID */, + const TBool aAcceptance, + const TDesC& aUserID, + const TDesC& aScreenName, + const TDesC& aGroupName, + const TDesC& aResponse, + TImpsCspIdentifier& /* aCspId */ ) + { + CHAT_DP_TXT( "Received response to our invitation" ); + if ( aAcceptance ) + { + CHAT_DP( D_CHAT_LIT( "%S accepts our invite to %S with comment %S" ), + &aScreenName, &aGroupName, &aResponse ); + } + else + { + CHAT_DP( D_CHAT_LIT( "%S rejects our invitation to %S with comment %S" ), + &aScreenName, &aGroupName, &aResponse ); + } + + // identification for user can be in aScreenName or in aUserId + TPtrC user( aUserID ); + if ( user.Length() == 0 ) + { + user.Set( aScreenName ); + } + + // signal the observers + TInt count( iInviteObservers.Count() ); + for ( TInt i( 0 ); i < count; i++ ) + { + if ( iInviteObservers[ i ] ) + { + // it's non-NULL + iInviteObservers[ i ]->HandleInvitationResponse( aAcceptance, user, + aGroupName, aResponse ); + } + } + } + + +// --------------------------------------------------------- +// CCAInviteManager::CancelGroupInviteUserRequestL +// (other items were commented in a header). +// --------------------------------------------------------- +// +void CCAInviteManager::HandleInviteCancelL( const TDesC& aInviteID, + const TDesC& /* aUserID */, + const TDesC& /* aScreenName */, + const TDesC& /* aGroupName */, + const TDesC& /* aResponse */, + TImpsCspIdentifier& /* aCspId */ ) + { + CHAT_DP_TXT( "Received cancelled invitation signal" ); + + MCAInvitation* invite = FindInvite( aInviteID ); + if ( invite ) + { + // signal the observers + TInt count( iInviteObservers.Count() ); + for ( TInt i( 0 ); i < count; i++ ) + { + if ( iInviteObservers[ i ] ) + { + // it's non-NULL + iInviteObservers[ i ]->HandleInvitationEventL( + MCAInviteObserver::EInviteCancel, invite ); + } + } + + // Failed remove can be safely ignored. + RemoveInviteL( invite ); + } + } + + +// --------------------------------------------------------- +// CCAInviteManager::HandleCompleteL +// (other items were commented in a header). +// --------------------------------------------------------- +// +void CCAInviteManager::HandleCompleteL( TInt aOperationId, + TImpsCspIdentifier& /* aCspId */ ) + { + CHAT_DP_TXT( "Received invitation's HandleCompleteL" ); + // If code added before HandleRequest, then make sure that + // code does not Leave before HandleRequest, because request + // response waiting does not stop (and waitnote) before calling + // HandleRequest + iRequestMapper->HandleRequest( aOperationId, KErrNone ); + } + +void CCAInviteManager::HandleInviteReadL() const + { + // signal the observers + TInt count( iInviteObservers.Count() ); + for ( TInt i( 0 ); i < count; i++ ) + { + if ( iInviteObservers[ i ] ) + { + // it's non-NULL + iInviteObservers[ i ]->HandleInvitationEventL( + MCAInviteObserver::EInviteRead, NULL ); + } + } + } + + +// --------------------------------------------------------- +// CCAInviteManager::PrepareGroupForInviteeL( const CCAInvitation& aInvitation ) +// Checks if group is closed. If it's closed, then check if invitee is in +// access-list. If not, then check is the logged user admin in group. +// If so, then try to add invitee to access list. +// (other items were commented in a header). +// --------------------------------------------------------- +// +void CCAInviteManager::PrepareGroupForInviteeL( + const CCAInvitationRequest& aInvitation ) + { + const TDesC& groupID = aInvitation.GroupID(); + + // Check if group is open or not + if ( iGroupManager->IsGroupOpenL( groupID ) ) + { + CHAT_DP_TXT( "PrepareGroupForInviteeL, Group is open for everyone" ); + return; + } + + CHAT_DP_TXT( "PrepareGroupForInviteeL, Group closed, fetching access lists" ); + + // Check if invitees are in access lists + CDesCArray* failedList = new ( ELeave ) CDesCArrayFlat( KArrayGranularity ); + CleanupStack::PushL( failedList ); + + TBool adminStatus = + iGroupManager->IsAllowedAccessL( groupID, aInvitation.Invitees(), + *failedList ); + + // Try to add not found users to access list as normal users + if ( failedList->Count() > 0 ) + { + // there is something in the list + + if ( !adminStatus ) + { + User::Leave( EUserNotAdmin ); + } + + CHAT_DP_TXT( "PrepareGroupForInviteeL, Trying to add new users to \ + access list as normal users" ); + + // adds to network. we don't know screen names + MCAGroupOperations* grOp = iGroupManager->GroupOperationsL( groupID ); + TInt err( grOp->AddMembersL( *failedList, *failedList ) ); + User::LeaveIfError( err ); + } + + CleanupStack::PopAndDestroy( failedList ); + } + + + +// --------------------------------------------------------- +// CCAInviteManager::RemoveInviteL +// (other items were commented in a header). +// --------------------------------------------------------- +// +TBool CCAInviteManager::RemoveInviteL( const MCAInvitation* aInvitation ) + { + TInt inviteCount( iInviteTrackerQueue.Count() ); + for ( TInt i( 0 ); i < inviteCount; i++ ) + { + if ( iInviteTrackerQueue[ i ]->Invitation() == aInvitation ) + { + delete iInviteTrackerQueue[ i ]; + iInviteTrackerQueue.Remove( i ); + iInviteTrackerQueue.Compress(); + + // Signal the observers + TInt count( iInviteObservers.Count() ); + for ( TInt i( 0 ); i < count; i++ ) + { + if ( iInviteObservers[ i ] ) + { + // Using read event to cause unread message indicators + // to be updated + iInviteObservers[ i ]->HandleInvitationEventL( + MCAInviteObserver::EInviteRead, NULL ); + } + } + + return ETrue; + } + } + return EFalse; + } + + +// --------------------------------------------------------- +// CCAInviteManager::FindInvite +// (other items were commented in a header). +// --------------------------------------------------------- +// +MCAInvitation* CCAInviteManager::FindInvite( const TDesC& aInviteId ) + { + TInt inviteCount( iInviteTrackerQueue.Count() ); + for ( TInt i( 0 ); i < inviteCount; i++ ) + { + if ( iInviteTrackerQueue[ i ]->Invitation()->InviteID().CompareC( + aInviteId, KCollationLevel, NULL ) == 0 ) + { + return iInviteTrackerQueue[ i ]->Invitation(); + } + } + return NULL; + } + + +// --------------------------------------------------------- +// CCAInviteManager::CreateInviteRequestL +// (other items were commented in a header). +// --------------------------------------------------------- +// +MCAInvitation* CCAInviteManager::CreateInviteRequestL( const TDesC& aInviteID, + const TDesC& aUserID, + const TDesC& aScreenName, + const TDesC& aGroupID, + const TDesC& aInviteReason, + const TInt aValidityPeriod ) + { + TPtrC groupName( aGroupID ); + MCAStoredGroups* groups = CCAStorageManagerFactory::GroupListInterfaceL(); + MCAStoredGroup* group = groups->FindGroup( aGroupID ); + if ( group ) + { + groupName.Set( group->GroupName() ); + } + + CCAInvitation* invitation = CCAInvitation::NewL( aInviteID, + aUserID, + aGroupID, + aScreenName, + groupName, + aInviteReason, + aValidityPeriod ); + + invitation->AddReadObserver( this ); + + return invitation; + } + +// End of File