locationsystemui/locationsysui/locverifier/src/lpdverifierplugin.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:06:48 +0200
changeset 0 667063e416a2
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
 * Copyright (c) 2002 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:  Verifier plug-in which derives from CPosPrivacyNotifier.
 *
 */

// INCLUDE FILES
#include <eikenv.h>
#include <eiknotapi.h>
#include <AknIconArray.h>
#include <apgcli.h>
#include <lbs/epos_rposrequestorstack.h>
#include <epos_csuplsettingsconstants.h>
#include <StringLoader.h>
#include <locverifierdlg.rsg>
#include "lpdverifierplugin.h"
#include "lpdrequestao.h"
#include "lpdrequestorprocessor.h"
#include "lpdverifierquerylauncher.h"
#include "lpdnotifierquerylauncher.h"
#include "lpdbasemodel.h"
#include "locconsts.h"
#include "locverifierdlgdebug.h"
#include "locfileutils.h"
#include "locrequestorutilsresolver.h"
#include "lpdperiodicprocessor.h"

// INCLUDE FILES
#include <s32mem.h>
#include "locphonenumberformat.h"
#include "locverifiercoverui.h"
// CONSTANTS

// The Increment size for the package buffer used for packing the descriptors
const TInt KReqBufferIncrSize = 256;
const TInt KLpdItemArrayGranularity = 50;

const TInt KNonPeriodicRequest = 0;
const TInt KPeriodicRequest = 1;

const TInt KNotifyMessageLength = 300;

// CONSTANTS

// Unnamed namespace for local definitions

const MEikSrvNotifierBase2::TNotifierPriority KNotifierPriority =
        MEikSrvNotifierBase2::ENotifierPriorityHigh;
const TUid KNotifierChannel =
    {
    0x100065ac
    };
_LIT_SECURE_ID(KUikonSrvSecureId,0x10003a4a);
#ifdef _DEBUG
_LIT( KPanicText, "CLpdVerifierPlugin" );
enum TPanicCode
    {
    KLpdErrGeneral = 1
    };
#endif

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::CLpdVerifierPlugin
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CLpdVerifierPlugin::CLpdVerifierPlugin() :
    iCurrentRequest(KPosNullQNRequestId), iPeriodicNotQue(
            KLpdItemArrayGranularity)

    {
    iEnv = CEikonEnv::Static();
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::ConstructL()
    {
    BaseConstructL(KNotifierChannel, KNotifierPriority);

    TFileName* resourceFile = new (ELeave) TFileName;
    CleanupStack::PushL(resourceFile);
    // these appends are always safe:
    resourceFile->Append(KLocNotifierRscPath);
    resourceFile->Append(KLocVerifierRscFileName);
    TFileName* dllDrive = new (ELeave) TFileName;
    CleanupStack::PushL(dllDrive);
    Dll::FileName(*dllDrive);
    LocFileUtils::GetNearestLanguageFileL(iEnv->FsSession(), *dllDrive,
            *resourceFile);
    CleanupStack::PopAndDestroy(dllDrive);
    iResourceOffset = iEnv->AddResourceFileL(*resourceFile);
    CleanupStack::PopAndDestroy(resourceFile);

    iRtorProcessor = CLpdRequestorProcessor::NewL();
    iPeriodicProcessor = CLpdPeriodicProcessor::NewL( *this );
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CLpdVerifierPlugin* CLpdVerifierPlugin::NewL()
    {
    CLpdVerifierPlugin* self = new (ELeave) CLpdVerifierPlugin;

    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);

    return self;
    }

// Destructor
CLpdVerifierPlugin::~CLpdVerifierPlugin()
    {
    // Destruction of this plugin should only occur only in shutdown
    // or in severe problem situation.

    // A very special scenario is that base class construction leaves and
    // this destructor is called. In that case CompleteAllRequests() causes
    // access violation (noticed this by checking source code of base class).
    if (NotifierBase())
        { // base class has been fully constructed, method call is safe
        CompleteAllRequests(KErrGeneral);
        }

    // It is enough to delete queries so when don't get callbacks.
    FreeQueryResources();
    iPeriodicNotQue.Close();
    delete iPeriodicProcessor;
    delete iRequestActiveObject;
    delete iRtorProcessor;
    iEnv->DeleteResourceFile(iResourceOffset);
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::HandleNewRequestL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::HandleNewRequestL(TPosQNRequestId aRequestId)
    {
    EnqueIfPeriodicL(aRequestId);
    // Check whether the notifier is already handling a request
    // If yes, do nothing for now.
    if (iRequestActiveObject)
        {
        return;
        }
    else
        {
        iRequestActiveObject = CLpdRequestAO::NewL(*this);
        iRequestActiveObject->ScheduleRequest();
        }
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::EnqueIfPeriodicL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::EnqueIfPeriodicL(TPosQNRequestId aRequestId)
    {
    SetCurrentRequestL(aRequestId);
    TRequestType requestType = RequestTypeL(aRequestId);
    CPosRequestor::TRequestType requestorType = CheckRequestTypeL();

    if (requestType == ENotification && requestorType
            == CPosRequestor::ERequestPeriodic)
        {
        TInt64 sessionId = -1;
        GetSessionIdL( sessionId );

        TLpdPeriodicReqInfo newReq(aRequestId, sessionId);

        if (iPeriodicProcessor)
            {
            if (iPeriodicProcessor->GetSessionId() == sessionId)
                {
                CompleteRequest(aRequestId, KErrNone);
                }
            return;
            }
        else
            {
            TIdentityRelation<TLpdPeriodicReqInfo> matcher(
                    TLpdPeriodicReqInfo::MatchSession);
            TInt index = iPeriodicNotQue.Find(newReq, matcher);

            // Remove if it was present in Que
            if (index == KErrNotFound)
                {
                iPeriodicNotQue.Append(newReq);
                }
            else
                {
                CompleteRequest(aRequestId, KErrNone);
                }
            }
        }

    if (KPosNullQNRequestId != iCurrentRequest)
        SetCurrentRequestL(iCurrentRequest);
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::HandleRequestCancelled
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::HandleRequestCancelled(TPosQNRequestId aRequestId)
    {
    // Check whether the request is coming from Uikon Server. 
    // If not reject this request.
    if (!CheckClientSecureId(KUikonSrvSecureId))
        {
        return;
        }

    // This method is called for Verification Query Cancellation.
    // There are 2 scenarios when the cancellation can come.
    // 1. The verification query for which the cancellation is done is 
    //         currently is running
    // 2. The verification query is not running currently but is in the 
    //         requests Queue maintained by the base class.
    //
    // Case 1 :
    //		
    // If there is a Verification query currently running and the requestId
    //         matches then the cancel notificaiton has to be popped up.
    //
    // Case 2 :
    //		
    //     1. A Verification query was popped up.
    //     2. The network timed out and sent a cancel request which popped 
    //           up a notification request.
    //     3. The network sends another verification query in the mean time
    //           and also cancels it. The resulting notification dialog will
    //           not be run since there is still a notification that has not
    //           been dismissed by the user.
    //
    // Hence in case 2 the notification information is maintained in a Que 
    // in the iRequestActiveObject. Once the current notification dialog 
    // closes and there are no more verification dialogs pending, the 
    // notification dialogs are run one after the other.

    if (aRequestId != iCurrentRequest)
        {
        if (aRequestId == KPosNullQNRequestId)
            {
            return;
            }
        //Put this new Notification Request on the queue and then process
        //it later from iRequestActiveObject(CLpdRequestAO class) RunL.		
        RPosRequestorStack* requestors = NULL;
            TRAP_IGNORE(
                    SetCurrentRequestL(aRequestId);
                    // requestors is allocated in iRtorProcessor and ownership is finally
                    // transferred to iRequestActiveObject.
                    requestors = iRtorProcessor->RetrieveRequestorsL( *this );
                    // Enqueue the request to iRequestActiveObject
                    iRequestActiveObject->EnqueueRequestL(RequestSource(),
                            CancelReason(),
                            QueryTimeoutStrategy(),
                            requestors););
        return;
        }

    iCancelInfo.iCancelled = ETrue;
    iCancelInfo.iReason = CancelReason();
    iCancelInfo.iDecision = QueryTimeoutStrategy();
    iCancelInfo.iSource = RequestSource();

    if (iCurrentRequestType == EQuery)
        { // Verification was cancelled
        __ASSERT_DEBUG( iVerifierQuery, HandleDebugAssertError() );
        __ASSERT_DEBUG( !iNotifier, HandleDebugAssertError() );
        iVerifierQuery->Cancel();
        }
    else
        {
        // It must be a notification then, this case is not probable but
        // we can cancel the dialog if this would happen.
        __ASSERT_DEBUG( iCurrentRequestType == ENotification,
                HandleDebugAssertError() );
        __ASSERT_DEBUG( !iVerifierQuery, HandleDebugAssertError() );
        __ASSERT_DEBUG( iNotifier, HandleDebugAssertError() );
        iNotifier->Cancel();
        }
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::HandleAllRequestCancelled
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::HandleAllRequestCancelled()
    {
    if (iCurrentRequest != KPosNullQNRequestId)
        { // current request requires some specific behavior
        HandleRequestCancelled(iCurrentRequest);
        }
    // Note that ScheduleRequest in the end of HandleRequestCancelled() allows
    // current call chain run to completion and resources are released after
    // that. Pending requests have been completed so they won't be processed.
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::HandleVerificationResultL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::HandleVerificationResultL(TInt aResultCode)
    {
    iVerifyResult = aResultCode;

        LOCVERIFIERDLGDEBUG1( "CLpdVerifierPlugin::HandleVerificationResultL(%d)",
                iVerifyResult );

    switch (iVerifyResult)
        {
        case KErrNone: // fall through
        case KErrAccessDenied:
            {
            // No need for rules now in 3.0
            break;
            }
        case KErrTimedOut:
            { // UI's internal timer expired
            break;
            }
        case KErrCancel:
            {
            __ASSERT_DEBUG( iCancelInfo.iCancelled, HandleAssertErrorL() );
            NotifyCancellationL(iCancelInfo.iSource, iCancelInfo.iReason,
                    iCancelInfo.iDecision);

            return; // don't handle next req. yet
            }
        case KErrAbort: // This is used for emergency call support
            {
            CompleteAllRequests(iVerifyResult);
            // ScheduleRequest() allows the current call chain
            // run to completion and resources are released after that.
            iRequestActiveObject->ScheduleRequest();
            return;
            }
        default:
            {
            iEnv->HandleError(iVerifyResult);
            break;
            }
        }

    CompleteCurrentAndContinue(iVerifyResult); // this request was handled
    }
// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::HandleNotificationResultL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::HandleNotificationResultL(TInt aResultCode)
    {

    TLpdPeriodicReqInfo newReq(iCurrentRequest, -1);
    TIdentityRelation<TLpdPeriodicReqInfo> matcher(
            TLpdPeriodicReqInfo::MatchPrivacy);
    TInt index = iPeriodicNotQue.Find(newReq, matcher);

    // Remove if it was present in Que
    if (index != KErrNotFound)
        {
        iPeriodicNotQue.Remove(index);
        }
    CompleteRequest(iCurrentRequest, aResultCode);
    iCurrentRequest = KPosNullQNRequestId;

    switch (aResultCode)
        {
        case KErrNone: // fall through
        case KErrTimedOut: // fall through
            {
            break;
            }
        case KErrCancel:
            {
            break;
            }
        case KErrAbort: // This is used for emergency call support
            {
            CompleteAllRequests(aResultCode);
            // ScheduleRequest() -> allows the current call chain
            // run to completion and resources are released after that.
            break;
            }
        default:
            {
            iEnv->HandleError(aResultCode);
            break;
            }
        }

    iRequestActiveObject->ScheduleRequest(); // handle next req.
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::HandleLeave
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::HandleLeave(TInt aError)
    {
        LOCVERIFIERDLGDEBUG1( "CLpdVerifierPlugin::HandleLeave(%d)", aError);
    // In this case user needs feedback about the error situation:
    iEnv->HandleError(aError);

    // In case of leave current request is completed with
    // iVerifyResult, but queue handling is still continued.
    // iVerifyResult is better completion code for request than aError.
    CompleteCurrentAndContinue(iVerifyResult);
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::HandleNextRequest
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::HandleNextRequest()
    {
    TRAPD( err, HandleNextRequestL() );
    if (err)
        {
        // In case of leave current request is completed with
        // error code, but queue handling is still continued.

        // If we couldn't start handling the request it is
        // better not to confuse user with an error note.

        CompleteCurrentAndContinue(iVerifyResult);
        }
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::HandleNextRequestL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::HandleNextRequestL()
    {

    // It is better to free previous query resources here, because
    // now all callback methods have finished (active object allowed
    // run to completion)
    this->FreeQueryResources();

    // Read the next request:
    RArray<TPosQNRequestId> requests;
    CleanupClosePushL(requests);
    GetRequestsL(requests);

    if (requests.Count() == 0)
        { // No more requests to handle
        CleanupStack::PopAndDestroy(); // requests
        // This is a very important step, it allows new requests
        // to flow in ( see HandleNewRequestL() ):
        delete iRequestActiveObject;
        iRequestActiveObject = NULL;
        return;
        }
    iCurrentRequest = requests[0];
    CleanupStack::PopAndDestroy(); // requests
    SetCurrentRequestL(iCurrentRequest);

    // Check whether the request is coming from Uikon Server. If not reject this request.
    if (!CheckClientSecureId(KUikonSrvSecureId))
        {
        CompleteCurrentAndContinue(KErrPermissionDenied);
        return;
        }
   
    // Check the request type
    iCurrentRequestType = RequestTypeL(iCurrentRequest);

    if ((CheckRequestTypeL() == CPosRequestor::ERequestPeriodic)
            && (iCurrentRequestType == ENotification))
        iRtorProcessor->SetRequestType(KPeriodicRequest);
    else
        iRtorProcessor->SetRequestType(KNonPeriodicRequest);

    iRtorProcessor->ReadRequestorsL(*this);

    if (iCurrentRequestType == EQuery)
        {
        HandleNextVerificationL();
        }
    else if (iCurrentRequestType == ENotification)
        {
        HandleNextNotificationL();
        }
    else
        {
        User::Leave(KErrNotSupported);
        }
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::HandleNextVerificationL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::HandleNextVerificationL()
    {
    __ASSERT_DEBUG( iCurrentRequest != KPosNullQNRequestId,
            HandleAssertErrorL() );
    __ASSERT_DEBUG( !iVerifierQuery, HandleAssertErrorL() );
    TInt suplRequest;
    if (CheckRequestTypeL() == CPosRequestor::ERequestPeriodic)
        suplRequest = 1;
    else
        suplRequest = 0;

    TPosRequestSource source(RequestSource());
    if (source == EPosRequestSourceNotAvailable)
        {
        CompleteCurrentAndContinue(KErrNone);
        }
    else
        {
        if(suplRequest)
        {	
        iPeriodicProcessor->SetRequestorIdL( CurrentRequest() );     
        iPeriodicProcessor->SetRequestTypeL(iCurrentRequestType);
        
        CPosRequestor* req = NULL;
        if( RequestorCountL() )
        {
          req = RequestorLC( 0 );
          CleanupStack::Pop();
          }
        iPeriodicProcessor->SetRequestorL( req );

      }
      
      iVerifierQuery = CLpdVerifierQueryLauncher::NewL(*this);
      TPosRequestDecision decision(QueryTimeoutStrategy());
      // Note that item is left in cleanupstack until StartQuery():
      if (suplRequest)
          iVerifierQuery->PrepareSuplVerificationResourcesL();
      else
          iVerifierQuery->PrepareVerificationResourcesL(source, decision);

       // Ownership of text is immediatelly transferred:
       CLpdBaseModel* requestors = iRtorProcessor->RtorNamesForVerifNotifL(
                iVerifierQuery->ListBoxL());
       iVerifierQuery->SetQueryTextArray(requestors);

        // Start the Verification query
        StartQueryDialogL(iVerifierQuery, EVerificationRequest, decision);
        }
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::HandleNextNotificationL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::HandleNextNotificationL()
    {
    __ASSERT_DEBUG( iCurrentRequest != KPosNullQNRequestId,
            HandleAssertErrorL() );
    
    if (CheckRequestTypeL() == CPosRequestor::ERequestPeriodic)
        HandleNextPeriodicNotificationL();
    else
        HandleNextNonPeriodicNotificationL();

    }
// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::HandleNextNonPeriodicNotificationL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::HandleNextNonPeriodicNotificationL()
    {
    __ASSERT_DEBUG( iCurrentRequest != KPosNullQNRequestId,
            HandleAssertErrorL() );
    __ASSERT_DEBUG( !iNotifier, HandleAssertErrorL() );

    if (RequestSource() != EPosRequestSourceNetwork)
        { // Notifications are supported only for network requests
        User::Leave(KErrNotSupported);
        }

    TPosNotificationReason reason = NotificationReason();
    switch (reason)
        {
        // Decision without user's consent:
        case EPosDecisionByRequestSource:
            // Policy conflict, network timeout occurred before user's
            // response was received
            {
          
            TPosRequestDecision decision = LocationRequestDecision();
            if(!iNotifier)
            iNotifier = CLpdNotifierQueryLauncher::NewL(*this);
            iNotifier->PrepareNotificationResourcesL(reason, decision);
            CLpdBaseModel* requestors =
                    iRtorProcessor->RtorNamesForVerifNotifL(
                            iNotifier->ListBoxL());

            iNotifier->SetQueryTextArray(requestors);

            // Start the notification query
            StartQueryDialogL(iNotifier, ENotification, decision);
            break;
            }
        case EPosVerificationTimeout:
            {
            TPosRequestDecision decision = LocationRequestDecision();
            if(!iNotifier)
            iNotifier = CLpdNotifierQueryLauncher::NewL(*this);
            iNotifier->PrepareNotificationResourcesL(reason, decision);
            CLpdBaseModel* requestors =
                    iRtorProcessor->RtorNamesForVerifNotifL(
                            iNotifier->ListBoxL());
            iNotifier->SetQueryTextArray(requestors);

            // Start the notification query
            StartQueryDialogL(iNotifier, ENotificationTimeout, decision);

            break;
            }
        case EPosNotificationReasonNotAvailable: // fall through
        default: // Future extensions -> EPosNotificationReasonNotAvailable
            {
            User::Leave(KErrNotSupported);
            break;
            }
        }
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::HandleNextPeriodicNotificationL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::HandleNextPeriodicNotificationL()
    {
    __ASSERT_DEBUG( iCurrentRequest != KPosNullQNRequestId,
            HandleAssertErrorL() );

    if (RequestSource() != EPosRequestSourceNetwork)
        { // Notifications are supported only for network requests
        User::Leave(KErrNotSupported);
        }

    TPosNotificationReason reason = NotificationReason();

    switch (reason)
        {
        // Decision without user's consent:
        case EPosDecisionByRequestSource:
            // Policy conflict, network timeout occurred before user's
            // response was received
            {
            iPeriodicProcessor->SetRequestorIdL( CurrentRequest() );     
            iPeriodicProcessor->SetRequestTypeL(iCurrentRequestType);
            CPosRequestor* req = NULL;
            if( RequestorCountL() )
            {
            req = RequestorLC( 0 );
            CleanupStack::Pop();
            }
            iPeriodicProcessor->SetRequestorL( req );
        
            TPosRequestDecision decision = LocationRequestDecision();
            
            if(!iNotifier)
            iNotifier = CLpdNotifierQueryLauncher::NewL(*this);

            TInt64 sessionId = -1;
            sessionId = iRtorProcessor->GetSessionId();
            iPeriodicProcessor->SetSessionIdL(sessionId);

            HBufC* requestorName = NULL;
            if (iRtorProcessor->Requestors().Count() == 0)
                {
                requestorName = StringLoader::LoadL(R_LPD_UNKNOWN_REQUESTER);
                }
            else
                {
                const CPosRequestor& requestor =
                        *(iRtorProcessor->Requestors())[1];
                iUtils = CLocRequestorUtilsResolver::NewL();
                requestorName = iUtils->RequestorNameL(requestor);
                if ((requestorName->Des()).CompareC(_L("Unknown")) == 0)
                    {
                    requestorName = NULL;
                    requestorName = StringLoader::LoadL(
                            R_LPD_UNKNOWN_REQUESTER);
                    }
                delete iUtils;
                iUtils = NULL;
                }
            iPeriodicProcessor->SetRequestorNameL(requestorName);

            delete requestorName;
            iNotifier->PrepareSuplNotificationResourcesL(reason);

            HBufC* notifyMessage = HBufC::NewLC(KNotifyMessageLength);
            TRAPD( err, iPeriodicProcessor->NotificationMessageTextL(notifyMessage));
  
            if (err == KErrNotFound)
                {
                    CleanupStack::PopAndDestroy(); // notifyMessage
                    CompleteCurrentAndContinue(err);
                }
            else
                {
                iNotifier->SetMessageQueryTextL(notifyMessage->Des(),
                        iPeriodicProcessor->LinkCallBack());

                CleanupStack::PopAndDestroy(); // notifyMessage
                // Start the notification query
                StartQueryDialogL(iNotifier, ESuplPeriodicNotification,
                        decision);
                }
            break;
            }
        case EPosVerificationTimeout:
            {
            break;
            }
        case EPosNotificationReasonNotAvailable: // fall through
        default: // Future extensions -> EPosNotificationReasonNotAvailable
            {
            User::Leave(KErrNotSupported);
            break;
            }
        }
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::NotifyCancellationL
// Helper method
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::NotifyCancellationL(TPosRequestSource aSource,
        TPosVerifyCancelReason aReason, TPosRequestDecision aDecision)
    {
    __ASSERT_DEBUG( iCurrentRequestType == EQuery, HandleAssertErrorL() );

    if (aSource == EPosRequestSourceNetwork)
        { // Notifications supported only for network-originated requests

        switch (aReason)
            {
            case EPosCancelReasonTimeout:
                {
                __ASSERT_DEBUG( !iNotifier, HandleAssertErrorL() );
				if(aDecision != EPosDecisionNotAvailable)
					{
	                iNotifier = CLpdNotifierQueryLauncher::NewL( *this );
	                iNotifier->PrepareCancelNotifResourcesL( aDecision );
	                CLpdBaseModel* requestors =
	                                iRtorProcessor->RtorNamesForVerifNotifL(
	                                                    iNotifier->ListBoxL() );
	                iNotifier->SetQueryTextArray( requestors );

                    // Start the notification query
                    StartQueryDialogL( iNotifier,
                                       ECancelNotification,
                                       aDecision );
                
	                return;
					}
				break;
                }
            case EPosCancelReasonNotAvailable: // fall through
            default: // future extensions -> EPosCancelReasonNotAvailable
                {
                break;
                }
            }
        }

    // If notification dialog was not launched, handle next request:
    iRequestActiveObject->ScheduleRequest();

    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::CompleteCurrentAndContinue
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::CompleteCurrentAndContinue(TInt aResultCode)
    {
    if (iCurrentRequest != KPosNullQNRequestId)
        {
        CompleteRequest(iCurrentRequest, aResultCode);
        }
    iCurrentRequest = KPosNullQNRequestId;

    __ASSERT_DEBUG( iRequestActiveObject, HandleDebugAssertError() );
    iRequestActiveObject->ScheduleRequest(); // handle next req.
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::FreeQueryResources
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::FreeQueryResources()
    {
    if(iPeriodicProcessor)
    iPeriodicProcessor->ResetParameters();
    iCurrentRequest = KPosNullQNRequestId;
    delete iVerifierQuery;
    iVerifierQuery = NULL;
    iVerifyResult = KErrGeneral;
    iCancelInfo.iCancelled = EFalse;
    delete iNotifier;
    iNotifier = NULL;
    if (iRtorProcessor)
        { // if already construction fails iRtorProcessor may
        // be NULL, otherwise it points to an instance.
        iRtorProcessor->ResetAndDestroyRequestors();
        }
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::HandleAssertErrorL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::HandleAssertErrorL() const
    {
#ifdef _DEBUG        
    User::Panic(KPanicText, KLpdErrGeneral);
#else
    User::Leave( KErrCorrupt );
#endif
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::HandleDebugAssertError
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::HandleDebugAssertError() const
    {
#ifdef _DEBUG
    User::Panic(KPanicText, KLpdErrGeneral);
#endif
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::NotifyTimeoutL
// Helper method
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::NotifyCancellationL(
    TPosRequestSource aSource,
    TPosVerifyCancelReason aReason,
    TPosRequestDecision aDecision,
    const RPosRequestorStack& aRequestors )
    {
    if ( aSource == EPosRequestSourceNetwork )
        { // Notifications supported only for network-originated requests

        switch ( aReason )
            {
            case EPosCancelReasonTimeout:
                {
                __ASSERT_DEBUG( !iNotifier, HandleAssertErrorL() );
				if(aDecision != EPosDecisionNotAvailable)
					{
	                iNotifier = CLpdNotifierQueryLauncher::NewL( *this );
	                iNotifier->PrepareCancelNotifResourcesL( aDecision );
	                iRtorProcessor->ReadRequestorsL(aRequestors);
	                CLpdBaseModel* requestors =
	                                iRtorProcessor->RtorNamesForVerifNotifL(
	                                                    iNotifier->ListBoxL() );
	                iNotifier->SetQueryTextArray( requestors );
                    
                    // Start the notification query
                    StartQueryDialogL( iNotifier,
                                       ECancelNotification,
                                       aDecision );
                
	                return;
					}
				break;
                }
            case EPosCancelReasonNotAvailable: // fall through
            default: // future extensions -> EPosCancelReasonNotAvailable
                {
                break;
                }
            }
        }

    // If notification dialog was not launched, handle next request:
    iRequestActiveObject->ScheduleRequest();
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::StartQueryDialogL
// Starts the Query dialog
// @param aQueryDialog Query dialog that has to be started
// @param aDialogType  Dialog type
// @param aDecision    Decision Type
// -----------------------------------------------------------------------------
void CLpdVerifierPlugin::StartQueryDialogL(
        CLpdQueryLauncherBase* aQueryDialog, TDialogType aDialogType,
        TPosRequestDecision aDecision)
    {
    // Set the Command ID
    TInt coverUiCmd = CoverUICommandL(aDialogType, aDecision);

    aQueryDialog->SetCoverUICommand(coverUiCmd);
    // Set the Requestor buffer                               
    CBufFlat* reqBuffer = PackRequestorBufferL();
    CleanupStack::PushL(reqBuffer);

    TPtr8 reqBufferPtr(reqBuffer->Ptr(0));
    aQueryDialog->SetRequestorBuffer(reqBufferPtr);

    if (aDialogType == ESuplPeriodicNotification)
        aQueryDialog->StartSuplPeriodicQueryL();
    else
        aQueryDialog->StartQueryL();
    
    CleanupStack::PopAndDestroy(reqBuffer);


    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::PackRequestorBufferL
// Packs the Requestor buffer to send across to Cover UI. The 
// ownership of the buffer is transferred back to the callee
// @return CBufFlat*    Flat buffer containing the list of requestors    
// -----------------------------------------------------------------------------
//
CBufFlat* CLpdVerifierPlugin::PackRequestorBufferL()
    {
    // Construct the conversion buffers and the package buffer
    CBufFlat* requestorBuffer = CBufFlat::NewL(KReqBufferIncrSize);
    CleanupStack::PushL(requestorBuffer);

    // Opening a Write stream to assist in packing data onto CBufFlat
    RBufWriteStream writeStream;
    writeStream.Open(*requestorBuffer);
    CleanupClosePushL(writeStream);

    // Obtain the list of requestors from which the individual requestor
    // Ids can be obtained
    const RPointerArray<CPosRequestor>& requestors =
            iRtorProcessor->Requestors();

    // The buffer is packed according to the below mentioned
    // format.
    // 
    // | Count | Length(1) | String(1) | ..... | Length( Count ) | String( Count ) |
    // 
    // where,
    // Count   - ( 4 bytes ) - The number of requestor strings. 
    // Length(n) - ( 4 bytes ) - Length of the nth requestor string.
    // String(n) - ( Length(n) * 2 bytes ) - String for the nth requestor.
    // 
    // Each entry is packed one after another without any delimters between them
    //

    // Packing the count
    writeStream.WriteInt32L(requestors.Count());

    for (TInt i = 0; i < requestors.Count(); i++)
        {
        const CPosRequestor& req = *(requestors[i]);

        // Obtain the Requestor Id string
        TPtrC reqStr = req.RequestorIdString();

        // We need a 16 bit buffer for converting. Since the requestor strings that
        // need to be packed have to always be of the UCS-2 ( UNICODE ) format.
        // The buffer would be allocated just before copying the requestor content
        HBufC16* conversionBuf = NULL;
        TPtr16 conBufPtr(0, 0);

        // If the string is a phone number then it needs to be grouped and the
        // converted to a UNICODE string. If not, then simpy convert it to
        // a UNICODE string
        if (CPosRequestor::EIdFormatPhoneNumber == req.RequestorIdFormat())
            {
            // Creating the Phone number formatter for grouping
            CLocPhoneNumberFormat* formatter = CLocPhoneNumberFormat::NewL();
            CleanupStack::PushL(formatter);

            HBufC* groupedName = NULL;
            TRAPD( error, groupedName = formatter->PhoneNumberGroupL( reqStr ));
            if (error || !groupedName)
                {
                // If there was a Leave in the grouping function or the 
                // grouping failed then pack the original name

                // Allocate the conversion buffer and copy the Requestor string
                conversionBuf = HBufC16::NewL(reqStr.Length());
                conBufPtr.Set(conversionBuf->Des());

                // Copy the original string to the conversion buffer
                conBufPtr.Copy(reqStr);
                }
            else
                {
                // Take ownership of the grouped phone number buffer and 
                // copy it to the conversion buffer
                CleanupStack::PushL(groupedName);

                TPtr groupedNamePtr = groupedName->Des();

                // Allocate the conversion buffer and copy the Requestor string
                conversionBuf = HBufC16::NewL(groupedNamePtr.Length());
                conBufPtr.Set(conversionBuf->Des());

                // Copy the grouped string to the conversion buffer
                conBufPtr.Copy(groupedNamePtr);

                CleanupStack::PopAndDestroy(groupedName);
                }

            CleanupStack::PopAndDestroy(formatter);
            }
        else
            {
            // Copy the Requestor ID string

            // Allocate the conversion buffer and copy the Requestor string
            conversionBuf = HBufC16::NewL(reqStr.Length());
            conBufPtr.Set(conversionBuf->Des());

            // Copy the original string to the conversion buffer
            conBufPtr.Copy(reqStr);
            }

        // Push the Conversion buffer to the CleanupStack
        CleanupStack::PushL(conversionBuf);

        // The conversion buffer now contains the string in the UNICODE 
        // format. First pack the length of the string and then the 
        // actual string itself
        writeStream.WriteInt32L(conBufPtr.Length());

        TUint8* buffer = (TUint8*) (conBufPtr.Ptr());
        writeStream.WriteL(buffer, conBufPtr.Size());

        // Destroying the Conversion buffer before it goes out of scope
        CleanupStack::PopAndDestroy(conversionBuf);
        }

    // flush stream data to our buffer
    writeStream.CommitL();
    CleanupStack::PopAndDestroy(&writeStream);

    // The ownership of the requestor buffer should be transferred to the callee
    CleanupStack::Pop(requestorBuffer);

    return requestorBuffer;
    }

// -----------------------------------------------------------------------------
// Determines the Cover UI command corresponding to a paricular
// request
// @param  TRequestType         Request Type
// @param  TPosRequestDecision  Decision Type
// @return TInt                 Cover UI Command ID.
// -----------------------------------------------------------------------------
//
TInt CLpdVerifierPlugin::CoverUICommandL(TDialogType aRequestType,
        TPosRequestDecision aDecision)
    {
    TInt result = 0;

    if (EVerificationRequest == aRequestType)
        {
        switch (aDecision)
            {
            case EPosDecisionAccepted:
                {
                result = ECmdDefaultAccept;
                break;
                }
            case EPosDecisionRejected:
                {
                result = ECmdDefaultReject;
                break;
                }
            default:
                {
                result = ECmdDefaultNone;
                break;
                }
            }
        }
    else if ((ENotification == aRequestType) || (ESuplPeriodicNotification
            == aRequestType))
        {
        result = ECmdNotifyAccept;
        }
    else if (ENotificationTimeout == aRequestType)
        {
        switch (aDecision)
            {
            case EPosDecisionAccepted:
                {
                result = ECmdNotifyRejectFailure;
                break;
                }
            case EPosDecisionRejected:
                {
                result = ECmdNotifyAcceptFailure;
                break;
                }
            default:
                {
                User::Leave(KErrNotFound);
                break;
                }
            }
        }
    else if (ECancelNotification == aRequestType)
        {
        switch (aDecision)
            {
            case EPosDecisionAccepted:
                {
                result = ECmdNotifyAcceptTimeout;
                break;
                }
            case EPosDecisionRejected:
                {
                result = ECmdNotifyRejectTimeout;
                break;
                }
            default:
                {
                User::Leave(KErrNotFound);
                break;
                }
            }
        }
    else
        {
        User::Leave(KErrNotFound);
        }
    return result;
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::CheckRequestTypeL
// Checks the type of request and helps to know
// if a given request is of SUPL periodic type
// @param aCurrentRequest request id
// @return TRequestType type of request enum
// -----------------------------------------------------------------------------
CPosRequestor::TRequestType CLpdVerifierPlugin::CheckRequestTypeL()
    {
    CPosRequestor::TRequestType reqType = CPosRequestor::ENetworkTypeUnknown;
    if (RequestorCountL() > 0)
        {
        CPosRequestor* requestor = RequestorLC(0);
        reqType = requestor->RequestType();
        CleanupStack::PopAndDestroy(requestor);
        }
    return reqType;
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::GetSessionIdL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::GetSessionIdL( TInt64& aSessionId )
    {
    CPosRequestor* curRequestor = RequestorLC( 0 );
    TInt length = curRequestor->RequestorIdString().Length();
    TPtrC reqString(curRequestor->RequestorIdString().Mid( length - 3 ));
    TLex temp(reqString);
    temp.Val(aSessionId);
    CleanupStack::PopAndDestroy( curRequestor );
    }

// -----------------------------------------------------------------------------
// CLpdVerifierPlugin::UpdateCurrentNotifierL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CLpdVerifierPlugin::UpdateCurrentNotifierL()
    {
    // Confirm if the current request type is Notification before
    // processing/updating.

    __ASSERT_DEBUG( iCurrentRequestType == ENotification,
            HandleDebugAssertError() );
    __ASSERT_DEBUG( iPeriodicProcessor, HandleDebugAssertError() );
    if(iNotifier)
    iNotifier->CancelQuietly();
    HandleNextPeriodicNotificationL();
    
    }

//  End of File