memspyui/source/MemSpyViewMemoryTrackingAutoStartConfig.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:30:35 +0100
branchRCL_3
changeset 22 fad26422216a
parent 0 d6fe6244b863
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2009 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:
*
*/

#include "MemSpyViewMemoryTrackingAutoStartConfig.h"

// System includes
#include <AknQueryDialog.h>
#include <charconv.h>

// Engine includes
#include <memspy/engine/memspyengine.h>
#include <memspy/engine/memspyengineobjectprocess.h>
#include <memspy/engine/memspyengineobjectthread.h>
#include <memspy/engine/memspyengineobjectcontainer.h>
#include <memspy/engine/memspyengineobjectthreadinfoobjects.h>
#include <memspy/engine/memspyengineobjectthreadinfocontainer.h>
#include <memspy/engine/memspyengineprocessmemorytracker.h>
#include <memspy/engine/memspyenginehelperprocess.h>

// User includes
#include "MemSpyUiUtils.h"
#include "MemSpyViewMainMenu.h"
#include "MemSpyContainerObserver.h"

// Literal constants
_LIT8( KMemSpyProcessMemoryTrackerXmlFileMimeType, "text/xml" );
_LIT8( KMemSpyXmlSpec_MasterSection, "memspy_process_memory_tracking" );
_LIT8( KMemSpyXmlSpec_EntryProcess, "process" );
_LIT8( KMemSpyXmlSpec_EntryProcess_SID, "sid" );
_LIT8( KMemSpyXmlSpec_HexPrefix, "0x" );



CMemSpyViewMemoryTrackingAutoStartConfig::CMemSpyViewMemoryTrackingAutoStartConfig( CMemSpyEngine& aEngine, MMemSpyViewObserver& aObserver )
:   CMemSpyViewBase( aEngine, aObserver )
    {
    }


CMemSpyViewMemoryTrackingAutoStartConfig::~CMemSpyViewMemoryTrackingAutoStartConfig()
    {
    iProcessUids.Close();
    //
    delete iParser;
    delete iConverter;
    //
    delete iXMLFileNameInstallTime;
    delete iXMLFileNameUserSupplied;
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::ConstructL( const TRect& aRect, CCoeControl& aContainer, TAny* aSelectionRune )
    {
    CMemSpyViewBase::ConstructL( aRect, aContainer, aSelectionRune );

    // We only convert from UTF-8 to UTF-16
	iParser = CParser::NewL( KMemSpyProcessMemoryTrackerXmlFileMimeType, *this );
    iConverter = CCnvCharacterSetConverter::NewL();
    if  ( iConverter->PrepareToConvertToOrFromL( KCharacterSetIdentifierUtf8, iEngine.FsSession() ) == CCnvCharacterSetConverter::ENotAvailable )
	    {
		User::Leave(KErrNotFound);
		}

    // Search for standard files
    FindXmlInstallTimeL();
    FindXmlUserSuppliedL();

    // Copy items to our own temporary list...
    const RArray<TUid>& list = iEngine.HelperProcess().MemoryTrackingAutoStartProcessList();
    for( TInt i=0; i<list.Count(); i++ )
        {
        User::LeaveIfError( iProcessUids.Append( list[ i ] ) );
        }

    // Reset the title
    _LIT( KCustomTitle, "Process-Specific Memory Tracking" );
    SetTitleL( KCustomTitle );
    }


TMemSpyViewType CMemSpyViewMemoryTrackingAutoStartConfig::ViewType() const
    {
    return EMemSpyViewTypeThreadInfoItemMemoryTrackingAutoStartConfig;
    }


CMemSpyViewBase* CMemSpyViewMemoryTrackingAutoStartConfig::PrepareParentViewL()
    {
    CMemSpyViewMainMenu* parent = new(ELeave) CMemSpyViewMainMenu( iEngine, iObserver );
    CleanupStack::PushL( parent );
    parent->ConstructL( Rect(), *Parent(), (TAny*) ViewType() );
    CleanupStack::Pop( parent );

    return parent;
    }


TBool CMemSpyViewMemoryTrackingAutoStartConfig::HandleCommandL( TInt aCommand )
    {
    TBool handled = ETrue;
    //
    switch ( aCommand )
        {
    case EMemSpyCmdMemoryTrackingAutoStartItemAdd:
        OnCmdItemAddL();
        break;
    case EMemSpyCmdMemoryTrackingAutoStartItemEdit:
        OnCmdItemEditL();
        break;
    case EMemSpyCmdMemoryTrackingAutoStartItemDelete:
        OnCmdItemDeleteL();
        break;
    case EMemSpyCmdMemoryTrackingAutoStartItemDeleteAll:
        OnCmdItemDeleteAllL();
        break;
    case EMemSpyCmdMemoryTrackingAutoStartItemImport:
        OnCmdItemImportL();
        break;
    default:
        handled = CMemSpyViewBase::HandleCommandL( aCommand );
        break;
        }
    //
    return handled;
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::HandleListBoxItemActionedL( TInt /*aIndex*/ )
    {
    OnCmdItemEditL();
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::SetListBoxModelL()
    {
    CDesCArrayFlat* model = new(ELeave) CDesCArrayFlat(5);
    CleanupStack::PushL( model );

    TBuf<128> buf;
    _LIT( KProcUidFormatSpec, "\t0x%08x" );

    const TInt count = iProcessUids.Count();
    for( TInt i=0; i<count; i++ )
        {
        const TUid procUid = iProcessUids[ i ];
        //
        buf.Format( KProcUidFormatSpec, procUid.iUid );
        model->AppendL( buf );
        }

    // Set up list box
    CAknSettingStyleListBox* listbox = static_cast< CAknSettingStyleListBox* >( iListBox );
    listbox->Model()->SetItemTextArray( model );
    listbox->Model()->SetOwnershipType( ELbmOwnsItemArray );
    CleanupStack::Pop( model );
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::RefreshL()
    {
    SetListBoxModelL();
    CMemSpyViewBase::RefreshL();
    iListBox->HandleItemAdditionL();
    iListBox->DrawDeferred();
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::DynInitMenuPaneL( TInt aResourceId, CEikMenuPane* aMenuPane )
    {
    if  ( aResourceId == MenuCascadeResourceId() )
        {
        const TInt count = iProcessUids.Count();
        const TInt index = iListBox->CurrentItemIndex();

        // We cannot edit an item if none exists
        aMenuPane->SetItemDimmed( EMemSpyCmdMemoryTrackingAutoStartItemEdit, ( count == 0 || index < 0 || index > count - 1 ) );
        aMenuPane->SetItemDimmed( EMemSpyCmdMemoryTrackingAutoStartItemDelete, ( count == 0 || index < 0 || index > count - 1 ) );
        aMenuPane->SetItemDimmed( EMemSpyCmdMemoryTrackingAutoStartItemDeleteAll, ( count <= 1 || index > count - 1 ) );

        // We can only import items if an XML file is available
        const TBool xmlAvailable = ( iXMLFileNameInstallTime->Length() || iXMLFileNameUserSupplied->Length() );
        aMenuPane->SetItemDimmed( EMemSpyCmdMemoryTrackingAutoStartItemImport, !xmlAvailable );
        }
    }


TUint CMemSpyViewMemoryTrackingAutoStartConfig::MenuCascadeResourceId() const
    {
    return R_MEMSPY_MENUPANE_MEMORY_TRACKING_AUTOSTART;
    }


TInt CMemSpyViewMemoryTrackingAutoStartConfig::MenuCascadeCommandId() const
    {
    return EMemSpyCmdMemoryTrackingAutoStart;
    }
   
    
void CMemSpyViewMemoryTrackingAutoStartConfig::OnCmdItemAddL()
    {
    const TUid uid = ShowDialogL( KNullUid );
    if ( uid != KNullUid )
        {
        User::LeaveIfError( iProcessUids.Append( uid ) );
        SaveChangesL();
        RefreshL();
        iListBox->HandleItemAdditionL();
        iListBox->DrawDeferred();
        }
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnCmdItemEditL()
    {
    const TInt index = iListBox->CurrentItemIndex();
    if ( index >= 0 && index < iProcessUids.Count() )
        {
        TUid processUid = iProcessUids[ index ];
        processUid = ShowDialogL( processUid );
        //
        if ( processUid != KNullUid )
            {
            iProcessUids[ index ] = processUid;
            SaveChangesL();
            RefreshL();
            iListBox->HandleItemAdditionL();
            iListBox->DrawDeferred();
            }
        }
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnCmdItemDeleteL()
    {
    const TInt index = iListBox->CurrentItemIndex();
    if ( index >= 0 && index < iProcessUids.Count() )
        {
        iProcessUids.Remove( index );
        SaveChangesL();
        RefreshL();
        iListBox->HandleItemRemovalL();
        iListBox->DrawDeferred();
        
        const TInt newIndex = index - 1;
        const TInt count = iProcessUids.Count();
        if ( newIndex >=0 && newIndex < count )
            {
            iListBox->SetCurrentItemIndex( index );
            }
        }
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnCmdItemDeleteAllL()
    {
    iProcessUids.Reset();
    SaveChangesL();
    RefreshL();
    iListBox->HandleItemRemovalL();
    iListBox->DrawDeferred();
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnCmdItemImportL()
    {
    if  ( iXMLFileNameInstallTime->Length() )
        {
        CAknQueryDialog* importDialog = CAknQueryDialog::NewL();
        if  ( importDialog->ExecuteLD( R_MEMSPY_MEMORY_TRACKING_IMPORT_FROM_INSTALLED_XML_DIALOG ) )
            {
            TRAP_IGNORE( ParseL( *iXMLFileNameInstallTime ) );
            }
        }
    if  ( iXMLFileNameUserSupplied->Length() )
        {
        CAknQueryDialog* importDialog = CAknQueryDialog::NewL();
        if  ( importDialog->ExecuteLD( R_MEMSPY_MEMORY_TRACKING_IMPORT_FROM_USERDEFINED_XML_DIALOG ) )
            {
            TRAP_IGNORE( ParseL( *iXMLFileNameUserSupplied ) );
            }
        }

    SaveChangesL();
    RefreshL();
    iListBox->HandleItemRemovalL();
    iListBox->DrawDeferred();
    }


TUid CMemSpyViewMemoryTrackingAutoStartConfig::ShowDialogL( TUid aUid )
    {
    TUid uid = KNullUid;
    //
    _LIT( KProcessUidFormat, "%x" );
    TBuf<128> buf;
    buf.Format( KProcessUidFormat, aUid );
    //
    CAknTextQueryDialog* dialog = new(ELeave) CAknTextQueryDialog( buf );
    const TBool dialogActioned = ( dialog->ExecuteLD( R_MEMSPY_MEMORY_TRACKING_PROCESS_UID_DIALOG ) );
    //
    if ( dialogActioned )
        {
        // Validate the text
        uid = ValidateProcessUid( buf );
        }
    //
    return uid;
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::SaveChangesL()
    {
    iEngine.HelperProcess().SetMemoryTrackingAutoStartProcessListL( iProcessUids );
    Settings().StoreSettingsL();
    }


TUid CMemSpyViewMemoryTrackingAutoStartConfig::ValidateProcessUid( const TDesC& aUid )
    {
    TUid ret = KNullUid;
    TBool isValid = ETrue;
    //
    const TInt length = aUid.Length();
    for( TInt i=0; i<length && isValid; i++ )
        {
        const TChar charValue = aUid[ i ];
        //
        switch( charValue )
            {
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
        case 'a':
        case 'A':
        case 'b':
        case 'B':
        case 'c':
        case 'C':
        case 'd':
        case 'D':
        case 'e':
        case 'E':
        case 'f':
        case 'F':
            break;
        default:
            isValid = EFalse;
            break;
            }
        }
    //
    if ( isValid )
        {
        TUint32 val = 0;
        TLex lexer( aUid );
        if ( lexer.Val( val, EHex ) == KErrNone )
            {
            ret.iUid = val;
            }
        }
    //
    return ret;
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::FindXmlInstallTimeL()
    {
    RFs& fsSession = iEngine.FsSession();
    //
    TFileName* fileName = new(ELeave) TFileName();
    CleanupStack::PushL( fileName );
    //
    fsSession.PrivatePath( *fileName );
    //
    TFindFile findFile( fsSession );
    if  ( findFile.FindByPath( KMemSpyProcessMemoryTrackingAutoStartConfigFileName, fileName ) == KErrNone )
        {
        iXMLFileNameInstallTime = findFile.File().AllocL();
        }
    else
        {
        iXMLFileNameInstallTime = KNullDesC().AllocL();
        RDebug::Print( _L("CMemSpyViewMemoryTrackingAutoStartConfig::FindXmlInstallTimeL() - NO FILE FOUND") );
        }
    //
    CleanupStack::PopAndDestroy( fileName );
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::FindXmlUserSuppliedL()
    {
    TFindFile findFile( iEngine.FsSession() );
    if  ( findFile.FindByPath( KMemSpyProcessMemoryTrackingAutoStartConfigFileName, &KMemSpyProcessMemoryTrackingAutoStartConfigSearchPath ) == KErrNone )
        {
        iXMLFileNameUserSupplied = findFile.File().AllocL();
        }
    else
        {
        iXMLFileNameUserSupplied = KNullDesC().AllocL();
        RDebug::Print( _L("CMemSpyViewMemoryTrackingAutoStartConfig::FindXmlUserSuppliedL() - NO FILE FOUND") );
        }
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::ParseL( const TDesC& aFileName )
    {
	Xml::ParseL( *iParser, iEngine.FsSession(), aFileName );
    //
    const TInt error = iParserErrorCode;
    iParserErrorCode = KErrNone;
    //
	User::LeaveIfError( error );
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnSectionProcessL( const RAttributeArray& aAttributes )
    {
    TUid uid = KNullUid;
    TBool gotSID = EFalse;
    //
    const TInt count = aAttributes.Count();
	for( TInt i=0; i<count; i++ )
		{
		const TPtrC8 attrib( aAttributes[ i ].Attribute().LocalName().DesC() );
		const TPtrC8 value( aAttributes[ i ].Value().DesC() );
        //
		if  ( attrib.CompareF( KMemSpyXmlSpec_EntryProcess_SID ) == 0 )
			{
            if  ( gotSID )
                {
                User::LeaveIfError( KErrCorrupt );
                }
            else
                {
                if  ( value.Length() >= 8 )
                    {
                    TRadix radix = EDecimal;
                    TPtrC8 pValue( value );
                    //
                    if  ( value.Length() == 10 && value.Left( 2 ) == KMemSpyXmlSpec_HexPrefix )
                        {
                        pValue.Set( value.Mid( 2 ) );
                        radix = EHex;
                        }
                    //
                    TUint32 uidVal = 0;
                    TLex8 lexer( pValue );
                    const TInt err = lexer.Val( uidVal, radix );
                    User::LeaveIfError( err );
                    uid.iUid = uidVal;
                    gotSID = ETrue;
                    }
                }
			}
        }
    //
    if  ( gotSID )
        {
        User::LeaveIfError( iProcessUids.Append( uid ) );
        }
    else
        {
        User::Leave( KErrCorrupt );
        }
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnStartDocumentL( const RDocumentParameters& /*aDocParam*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnEndDocumentL( TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnStartElementL( const RTagInfo& aElement, const RAttributeArray& aAttributes, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    //
	const TPtrC8 name( aElement.LocalName().DesC() );
    //
    if  ( name.CompareF( KMemSpyXmlSpec_MasterSection ) == 0 )
		{
		iSeenMasterSection = ETrue;
		}
    else if ( iSeenMasterSection && name.CompareF( KMemSpyXmlSpec_EntryProcess ) == 0 )
        {
        OnSectionProcessL( aAttributes );
        }
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnEndElementL( const RTagInfo& /*aElement*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnContentL( const TDesC8& /*aBytes*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnStartPrefixMappingL( const RString& /*aPrefix*/, const RString& /*aUri*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnEndPrefixMappingL( const RString& /*aPrefix*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnIgnorableWhiteSpaceL( const TDesC8& /*aBytes*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnSkippedEntityL( const RString& /*aName*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnProcessingInstructionL( const TDesC8& /*aTarget*/, const TDesC8& /*aData*/, TInt aErrorCode )
    {
    User::LeaveIfError( aErrorCode );
    }


void CMemSpyViewMemoryTrackingAutoStartConfig::OnError( TInt aErrorCode )
    {
    iParserErrorCode = aErrorCode;
    }


TAny* CMemSpyViewMemoryTrackingAutoStartConfig::GetExtendedInterface( const TInt32 /*aUid*/ )
    {
    return NULL;
    }