wvuing/wvuieng/EngSrc/CCAInviteManager.cpp
changeset 0 094583676ce7
--- /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 <e32base.h>
+
+// 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