vpnui/vpnecomnotifier/src/vpnecomnotifier.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 09:14:51 +0200
changeset 0 33413c0669b9
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* Copyright (c) 2008 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:   VPN Ecom Notifier's implementation file
*
*/




#include <eikenv.h>
#include <bautils.h>

#include "logvpncommon.h"

#include <uikon/eiksrvui.h>  // Eikon server ui (for suppressing app -key)

#include "vpnecomnotifier.h"

#include "vpndialogmanagerecomstub.h"





CArrayPtrFlat<MEikSrvNotifierBase2>* createNotifierArrayL()
    {
    CArrayPtrFlat<MEikSrvNotifierBase2>* notifierList = new (ELeave) CArrayPtrFlat<MEikSrvNotifierBase2>(2);
    CleanupStack::PushL(notifierList);

    CVpnDialogManagerEcomStub* dlgManager = new (ELeave) CVpnDialogManagerEcomStub();
    CleanupStack::PushL(dlgManager);
    
    CVpnNotifier* notifier = new (ELeave) CVpnNotifier(KUidVpnDialogNotifier, 
                                                       KVpnNotifierResource, 
                                                       dlgManager);
    CleanupStack::PushL(notifier);
    
    notifierList->AppendL(notifier);
    
    CleanupStack::Pop(3); // notifierList, dlgManager, notifier
    
    return notifierList;
    }

CArrayPtr<MEikSrvNotifierBase2>* NotifierArray()
    {
    CArrayPtrFlat<MEikSrvNotifierBase2>* notifierList = NULL;
    
    TRAPD(err, notifierList = createNotifierArrayL()); 
    if(err)
        {
        notifierList->ResetAndDestroy();
        delete notifierList;
        notifierList = NULL;
        }
           
    return notifierList;
    }

const TImplementationProxy ImplementationTable[]=
    {
    IMPLEMENTATION_PROXY_ENTRY(0x10200EC8, NotifierArray)
    };

EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
    {
    aTableCount = sizeof(ImplementationTable)/sizeof(TImplementationProxy);
    return ImplementationTable;
    }




CVpnNotifier::CVpnNotifier(const TUid& aNotifierUid, const TDesC& aResourceFilename,
                               CVpnDialogManagerEcomStub* aDialogManager)
    {
    LOG_("-> CVpnNotifier::CVpnNotifier()");
    iEikEnv = CEikonEnv::Static();
    iNotifierUid = aNotifierUid;
    iResourceFilename.Set(aResourceFilename);
    iDialogManager = aDialogManager;
    // Added to overcome uninstallation problems
    iResourceFileLoaded = EFalse;
    LOG_("<- CVpnNotifier::CVpnNotifier()");
    }

CVpnNotifier::~CVpnNotifier()
    {
    LOG_("-> CVpnNotifier::~CVpnNotifier()");
    delete iDialogManager;
    LOG_("<- CVpnNotifier::~CVpnNotifier()");
    }

CVpnNotifier::TNotifierInfo CVpnNotifier::RegisterL()
    {
    LOG_("-> CVpnNotifier::RegisterL()");

    iInfo.iUid = iNotifierUid;
    iInfo.iChannel = KCrystalScreenOutputChannel;
    iInfo.iPriority = ENotifierPriorityLow;

    LOG_("<- CVpnNotifier::RegisterL()");

    return iInfo;
    }

// Added to overcome uninstallation problems    
void CVpnNotifier::LoadResourceFileL()
    {
    LOG_("-> CVpnNotifier::LoadResourceFileL()");
    if (!iResourceFileLoaded)
        {
        TFileName fileName = GetResourceFileNameL();
        iResourceFileOffset = iEikEnv->AddResourceFileL(fileName);
        iResourceFileLoaded = ETrue;
        }

    LOG_("<- CVpnNotifier::LoadResourceFileL()");
    }


void CVpnNotifier::CloseManagerDll() 
    {
    if (iRealDialogManager) 
        {
        LOG_(" Closing old dialog manager instance");


        LOG_(" Deleting");
        delete iRealDialogManager;
        iRealDialogManager = NULL;

        iDialogManager->SetDialogManager(NULL);

        LOG_(" Closing library");

        iDialogManagerLib.Close();
        
        LOG_(" Close completed");
        }
    }

// Added to overcome uninstallation problems
void CVpnNotifier::UnloadResourceFile()
    {
    LOG_("-> CVpnNotifier::UnloadResourceFile()");


    if (iResourceFileLoaded)
        {
        iEikEnv->DeleteResourceFile(iResourceFileOffset);
        iResourceFileLoaded = EFalse;
        }



    LOG_("<- CVpnNotifier::UnloadResourceFile()");
    }
    
CVpnNotifier::TNotifierInfo CVpnNotifier::Info() const
    {
    return iInfo;
    }

void CVpnNotifier::StartL(const TDesC8& aBuffer, TInt aReturnValue, const RMessagePtr2& aMessage)
    {
    LOG_("-> CVpnNotifier::StartL()");
    __ASSERT_DEBUG(aBuffer.Length() >= 4, _L("Input buffer is empty"));

    // Only one dialog can be shown at a time
    if (iDialog)
        {
        User::Leave(KErrInUse);
        }
    
    // Store output data references
    iMessage = aMessage;
    iReturnValue = aReturnValue;

    // Get input data to the local memory space
    HBufC8* input = HBufC8::NewL(aBuffer.Length());
    CleanupStack::PushL(input);
    input->Des().Copy(aBuffer);

    // The input consist of two parts in a single descriptor:
    // TVpnDialogInfo and the actual input that goes to the dialogs

    // First analyze the TVpnDialogInput info
    TVpnDialogInfo dialogInfo;
    TPckg<TVpnDialogInfo> pkgDialogInfo(dialogInfo);
    pkgDialogInfo.Copy(input->Left(sizeof(TVpnDialogInfo))); // 8 bit buffer -> size = length

    TInt dialogId = dialogInfo.DialogId();
    TInt noteDialogId = dialogInfo.NoteDialogId();
    

    // Then store the actual dialog input for later use
    TInt strLen = dialogInfo.NoteExtraInput().Length();
    if (strLen > 0) 
        {
        // Additional extra input (i.e. string replacement) was specified
        // in the dialog info structure, take it into use and pass it on.
        iInput = dialogInfo.NoteExtraInput().AllocL();
        }
    else 
        {
        iInput = HBufC8::NewL(input->Size() - sizeof(TVpnDialogInfo));
        iInput->Des().Copy(input->Mid(sizeof(TVpnDialogInfo)));
        }

    CleanupStack::PopAndDestroy(); // input

    if (!LaunchDialogL(dialogId, noteDialogId, *iInput))
        {
        User::Leave(KErrNotSupported);
        }
    LOG_("<- CVpnNotifier::StartL()");
    }

TPtrC8 CVpnNotifier::StartL( const TDesC8& /*aBuffer*/ )
    {
    LOG_("-> CVpnNotifier::StartL()");
    
    __ASSERT_DEBUG(EFalse, User::Panic(_L("Synchronous StartL not used"), 0)); // should here be ret KNullDesC8() also?
    
    LOG_("<- CVpnNotifier::StartL()");
    
    return NULL;
    }

TPtrC8 CVpnNotifier::UpdateL( const TDesC8& /*aBuffer*/ )
    {
    LOG_("-> CVpnNotifier::UpdateL()");

    LOG_("<- CVpnNotifier::UpdateL()");

    return KNullDesC8();
    }

void CVpnNotifier::Cancel()
    {
    LOG_("-> CVpnNotifier::Cancel()");
    if (iDialog)
        {
        TRAP_IGNORE(iDialog->CancelL());
        iDialog = NULL;
        }
    LOG_("<- CVpnNotifier::Cancel()");
    }

void CVpnNotifier::Release()
    {
    LOG_("-> CVpnNotifier::Release()");

    UnloadResourceFile();
    CloseManagerDll();
    delete this;

    LOG_("<- CVpnNotifier::Release()");
    }

TBool CVpnNotifier::LaunchDialogL(TInt aDialogId, TInt aNoteDialogId, const TDesC8& aInput)
    {
    LOG_("-> CVpnNotifier::LaunchDialogL()");
	((CEikServAppUi*)(CEikonEnv::Static())->EikAppUi())->SuppressAppSwitching(ETrue);

    // To ensure that we indeed do get the most recent (possibly updated) version
    // of both the resource file, and the DLL that uses resource IDs.
    UnloadResourceFile();
    LoadResourceFileL();
    
    CloseManagerDll();
    LoadManagerDllL();

    iDialog = iDialogManager->LaunchDialogL(this, aDialogId, aNoteDialogId, aInput);
    if (iDialog)
        {
        LOG_("<- CVpnNotifier::LaunchDialogL() (ETrue)");
        return ETrue;
        }
    else
        {
        UnloadResourceFile();
        CloseManagerDll();
        LOG_("<- CVpnNotifier::LaunchDialogL() (couldn't instantiate dialog)");
        return EFalse;
        }
    }
    
TFileName CVpnNotifier::GetResourceFileNameL()
    {
    LOG_("-> CVpnNotifier::GetResourceFileNameL()");
    RFs& fsSession = iEikEnv->FsSession(); 

    TDriveList driveList;
    User::LeaveIfError(fsSession.DriveList(driveList));

    TInt driveNumber;
    TDriveName drive = _L("a:");

    TFileName resName;
    TInt foundIt = EFalse;

    LOG_(" Starting drive letter iteration");
    for (driveNumber = EDriveA, drive[0] = 'a';
         driveNumber <= EDriveZ;
         driveNumber++, drive[0]++)
        {
        if (!driveList[driveNumber])
            {
            LOG_("  Continue");
            continue;
            }

        TParse parse;
        parse.Set(drive, &iResourceFilename, NULL);

        resName.Copy(parse.FullName()); 
        
        LOG_1("  Resource filename: '%S'", &resName);

        BaflUtils::NearestLanguageFile(iEikEnv->FsSession(), resName);

        TEntry entry;
        if (fsSession.Entry(resName, entry) == KErrNone)
            {
            LOG_("  Found it!");
            foundIt = ETrue;
            break;
            }
        }

    if (!foundIt)
        {
        LOG_(" Didn't find it!");
        User::Leave(KErrNotFound);
        }

    LOG_("<- CVpnNotifier::GetResourceFileNameL()");

    // If the file name was found, it will stay in the cleanup stack
    return resName;
    }

void CVpnNotifier::DialogCompleteL(TInt aReturnCode, TVpnDialogOutput& aOutput)
    {
    LOG_("-> CVpnNotifier::DialogCompleteL()");

    // NOTE! this doesn't work with own notifier server 
    // Activate apps -key again
    //
	((CEikServAppUi*)(CEikonEnv::Static())->EikAppUi())->SuppressAppSwitching(EFalse);

    TPckgBuf<TVpnDialogOutput> outBuf(aOutput);
    iMessage.WriteL(iReturnValue, outBuf);
    iMessage.Complete(aReturnCode);
    iDialog = NULL;
    delete iInput; iInput = NULL;
    // Added to overcome uninstallation problems
    UnloadResourceFile();
    iManager->CancelNotifier(iNotifierUid);

    LOG_("<- CVpnNotifier::DialogCompleteL()");

    }

void CVpnNotifier::DialogComplete(TInt aReturnCode)
    {
    LOG_("-> CVpnNotifier::DialogComplete()");

    // NOTE! this doesn't work with own notifier server 
    // Activate apps -key again
    //
	((CEikServAppUi*)(CEikonEnv::Static())->EikAppUi())->SuppressAppSwitching(EFalse);

    iMessage.Complete(aReturnCode);
    iDialog = NULL;
    delete iInput; iInput = NULL;
    // Added to overcome uninstallation problems
    UnloadResourceFile();
    iManager->CancelNotifier(iNotifierUid);    

    LOG_("<- CVpnNotifier::DialogComplete()");

    }

void CVpnNotifier::LoadManagerDllL() 
    {
    LOG_("-> CVpnNotifier::LoadManagerDll()");

    LOG_(" Loading manager again");

    TInt status = iDialogManagerLib.Load(KVpnDialogManagerDll, KNullUid);

    LOG_1(" DLL load status: %d", status);

    if (status == KErrNone)
        {
        LOG_(" Suitable DLL found, instantiating VPN dialog manager");
        
        TLibraryFunction entry = iDialogManagerLib.Lookup(1);
        
        LOG_(" Entry point found");

        // Constructor at the given ordinal may leave, even if it's not evident
        // from the syntax
        iRealDialogManager = (MVpnDialogManager*)entry();
        iDialogManager->SetDialogManager(iRealDialogManager);

        LOG_(" Dialog manager instantiated");
        }
    else 
        {
        LOG_(" (LEAVE) Dialog manager DLL not found!");
        User::Leave(status);
        }

    LOG_("<- CVpnNotifier::LoadManagerDll() (OK)");
    }