uifw/AvKon/src/AknTasHook.cpp
changeset 0 2f259fa3e83a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AvKon/src/AknTasHook.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,677 @@
+/*
+* 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: Avkon testability hook class definitions.
+*
+*/
+
+
+// INCLUDES
+#include <AknTasHook.h>
+#include <TasHookingInternalCRKeys.h>
+#include "AknBatteryStrength.h"
+#include "AknSignalStrength.h"
+#include <centralrepository.h>
+#include <AknTasPluginInterface.h>
+#include <TasDataModelInterface.h>
+
+// CONSTANTS
+const TUid KUidTasHook =    { 0xE000DEC4 };
+const TInt KTasHookingOff =   0;
+const TInt KTasHookingOn =    1;
+
+// MACROS
+
+    /**
+     * DEBUGPRINT
+     * 
+     * Simple wrapper macro for the RDebug::Print utility.
+     *
+     * Usage:
+     * 
+     *  DEBUGPRINT( ( _L( "CAknTasHook::ConstructL: Error %d in doing stuff" ), error ) )
+     * 
+     */
+    #ifdef _DEBUG
+    #define DEBUGPRINT( aFormatString ) { RDebug::Print aFormatString; }
+    #else
+    #define DEBUGPRINT( aFormatString ) {}
+    #endif
+
+// FORWARD DECLARATIONS
+class CAknTasClassInfo;
+class CAknTasObjectInfo;
+
+// CLASS DEFINITIONS
+
+CAknTasClassInfo::CAknTasClassInfo() :
+    iClassName( NULL )
+    {
+    }
+
+CAknTasClassInfo::~CAknTasClassInfo()
+    {
+    delete iClassName;
+    }
+
+void CAknTasClassInfo::ConstructL( TDesC& aClassName )
+    {
+    // Allocate a copy of the given descriptor and take ownership of it 
+    iClassName = aClassName.AllocL();
+    }
+                
+const TDesC& CAknTasClassInfo::GetClassName() const
+    {
+    return *iClassName;
+    }
+
+TInt CAknTasClassInfo::MatchName( 
+    const CAknTasClassInfo& aInfo1, 
+    const CAknTasClassInfo& aInfo2 )
+    {
+    if ( aInfo1.GetClassName() == aInfo2.GetClassName() )
+        {
+        return 1;
+        }
+    return 0;
+    }
+    
+CAknTasObjectInfo::CAknTasObjectInfo()
+    {    
+    }
+
+CAknTasObjectInfo::~CAknTasObjectInfo()
+    {
+    if ( iClassInfoArray )
+        {        
+        iClassInfoArray->ResetAndDestroy();
+        delete iClassInfoArray;
+        }
+    }
+    
+void CAknTasObjectInfo::ConstructL( 
+    TAny* aObjPtr, 
+    TAknTasHookObjectType aObjType )
+    {
+    iObjPtr = aObjPtr; // not owned
+    if ( aObjPtr )
+        {
+        iClassInfoArray = new ( ELeave ) RPointerArray<CAknTasClassInfo>; // owned
+        iControlKey = TUint32( aObjPtr );
+        iObjType = aObjType;
+        }
+    else
+        {
+        iControlKey = 0;
+        }
+    }
+
+TInt CAknTasObjectInfo::MatchByControl(
+    const CAknTasObjectInfo& aInfo1, 
+    const CAknTasObjectInfo& aInfo2 )
+    {
+    if ( aInfo1.iControlKey == aInfo2.iControlKey )
+        {
+        return 1;
+        }
+    return 0;        
+    }
+
+void CAknTasObjectInfo::AddL( CAknTasClassInfo* aObjPtr )
+    {
+    iClassInfoArray->AppendL( aObjPtr );
+    }
+    
+EXPORT_C TBool CAknTasObjectInfo::IsA( TPtrC aClassName )
+    {
+    CAknTasClassInfo* classInfo = NULL;
+    TRAPD( err,
+            classInfo = new ( ELeave ) CAknTasClassInfo();
+            CleanupStack::PushL( classInfo );
+            classInfo->ConstructL( aClassName );
+            CleanupStack::Pop( classInfo ) );
+    if ( err )
+        {
+        if ( classInfo )
+            {
+            CleanupStack::PopAndDestroy( classInfo );
+            }
+        return EFalse;
+        }
+        
+    TIdentityRelation<CAknTasClassInfo> matcher( CAknTasClassInfo::MatchName );
+    TInt position = iClassInfoArray->Find( classInfo, matcher );
+    delete classInfo;
+    if ( position != KErrNotFound )
+        {        
+        classInfo = ( *iClassInfoArray )[position];
+        return ETrue;
+        }        
+    return EFalse;
+    }
+ 
+//
+// Heap descriptor ownership passed to caller!
+//
+EXPORT_C HBufC* CAknTasObjectInfo::GetClassNames()
+    {
+    // Sum up the class name lengths and add room for the separators
+    TInt bufLength( 0 );
+    for ( TInt i = 0; i < iClassInfoArray->Count(); i++ )
+        {
+        bufLength += ( *iClassInfoArray )[i]->GetClassName().Length() + 1;
+        }
+    
+    // Create a buffer of needed length and make it empty
+    HBufC* buf = NULL;
+    TRAPD( err, 
+            buf = HBufC::NewLC( bufLength );
+            CleanupStack::Pop( buf ) );
+    if ( err )
+        {
+        return NULL;
+        }
+    TPtr modifiableBuf = buf->Des();
+    modifiableBuf.Zero();
+    
+    if ( iClassInfoArray->Count() <= 0 )
+        {
+        return buf;
+        }
+    
+    // Append class names and separators
+    for ( TInt i = 0; i < iClassInfoArray->Count(); i++ )
+        {
+        modifiableBuf.Append( ( *iClassInfoArray )[i]->GetClassName() );
+        
+        if ( i + 1 < iClassInfoArray->Count() )
+            {
+            modifiableBuf.Append( _L( ":" ) );
+            }
+        }
+    
+    return buf;
+    }
+
+EXPORT_C TAny* CAknTasObjectInfo::GetControl() const
+    {
+    return iObjPtr;
+    }
+
+EXPORT_C TAknTasHookObjectType CAknTasObjectInfo::Type() const
+    {
+    return iObjType;
+    }
+                    
+CAknTasHook::CAknTasHook() :
+    CCoeStatic( KUidTasHook ),
+    iTasHookingEnabled( EFalse ),
+    iTasHookStoringEnabled( EFalse )
+    {    
+    }
+    
+CAknTasHook* CAknTasHook::InstanceL()
+    {
+    CAknTasHook* instance = 
+        static_cast<CAknTasHook*> ( CCoeEnv::Static( KUidTasHook ) );
+    if ( !instance )
+        {
+        instance = new ( ELeave ) CAknTasHook();
+        CleanupStack::PushL( instance );
+        instance->ConstructL();
+        CleanupStack::Pop( instance );
+        }
+    return instance;
+    }
+
+CAknTasHook* CAknTasHook::Self()
+    {
+    CAknTasHook* instance = 
+        static_cast<CAknTasHook*> ( CCoeEnv::Static( KUidTasHook ) );
+    if ( !instance )
+        {
+        return NULL;
+        }
+    return instance;
+    }
+
+CAknTasHook::~CAknTasHook()
+    {
+    delete iTasPlugin;
+    REComSession::FinalClose();
+    if ( iHookingNotifyHandler )
+        {
+        iHookingNotifyHandler->StopListening();
+        delete iHookingNotifyHandler;
+        }
+    if ( iHookStoringNotifyHandler )
+        {
+        iHookStoringNotifyHandler->StopListening();
+        delete iHookStoringNotifyHandler;
+        }
+    delete iTasHookingRepo;
+    if ( iObjectInfoArray )
+        {           
+        iObjectInfoArray->ResetAndDestroy();
+        delete iObjectInfoArray;
+        }
+    }
+
+void CAknTasHook::ConstructL()
+    {
+    iObjectInfoArray = new ( ELeave ) RPointerArray<CAknTasObjectInfo>; // owned
+
+    // Connect to TAS hooking CenRep repository
+    TRAPD( error, iTasHookingRepo = CRepository::NewL( KCRUidTasHooking ) );
+    if ( error != KErrNone )
+        {
+        DEBUGPRINT( ( _L( "   CAknTasHook::ConstructL: Error %d in connecting to key 0x%x" ), error, KCRUidTasHooking.iUid ) )
+        User::Leave( error );
+        }
+        
+    // Process the initial values and start listening 
+    // for key changes in this repository
+    TRAP( error, iHookingNotifyHandler = CreateNotifyHandlerL( *iTasHookingRepo, KTasHooking ) );
+    if ( error != KErrNone )
+        {
+        DEBUGPRINT( ( _L( "   CAknTasHook::ConstructL: Error %d in creating CenRep notify handler" ), error ) )
+        User::Leave( error );
+        }
+    TRAP( error, iHookingNotifyHandler->StartListeningL() );
+    if ( error != KErrNone )
+        {
+        DEBUGPRINT( ( _L( "   CAknTasHook::ConstructL: Error %d in starting to listen" ), error ) )
+        User::Leave( error );
+        }
+    TRAP( error, iHookStoringNotifyHandler = CreateNotifyHandlerL( *iTasHookingRepo, KTasHookStoring ) );
+    if ( error != KErrNone )
+        {
+        DEBUGPRINT( ( _L( "   CAknTasHook::ConstructL: Error %d in creating CenRep notify handler" ), error ) )
+        User::Leave( error );
+        }
+    TRAP( error, iHookStoringNotifyHandler->StartListeningL() );
+    if ( error != KErrNone )
+        {
+        DEBUGPRINT( ( _L( "   CAknTasHook::ConstructL: Error %d in starting to listen" ), error ) )
+        User::Leave( error );
+        }
+    }
+    
+CCenRepNotifyHandler* CAknTasHook::CreateNotifyHandlerL( 
+    CRepository& aRepository, 
+    TUint32 aKey )
+    {
+    // Process the initial value, the 1st notication is only received when the
+    // value changes so we need to see if the hooking has already been activated
+    TInt initialValue;
+    TInt error = aRepository.Get( aKey, initialValue );
+    if ( error != KErrNone )
+        {
+        DEBUGPRINT( ( _L( "   CAknTasHook::CreateNotifyHandlerL: Error %d in getting key value" ), error ) )
+        User::Leave( error );
+        }
+    else
+        {
+        HandleNotifyInt( aKey, initialValue );
+        }
+        
+    // Create a new notify handler for the given integer key
+    return CCenRepNotifyHandler::NewL( *this, aRepository, CCenRepNotifyHandler::EIntKey, aKey );
+    }
+
+TBool CAknTasHook::Initialized()
+    {
+    if ( iObjectInfoArray )
+        {
+        return ETrue;
+        }
+    return EFalse;
+    }
+        
+EXPORT_C void CAknTasHook::AddL( 
+    TAny* aObjPtr, 
+    TPtrC aStrPtr, 
+    TAknTasHookObjectType aObjType )
+    {
+    if ( !aObjPtr )
+        {
+        return;
+        }
+    
+    CAknTasHook* mePtr = InstanceL();   
+    if ( mePtr )
+        {
+        mePtr->AddInfoL( aObjPtr, aStrPtr, aObjType );
+        }
+    }
+    
+void CAknTasHook::AddInfoL( 
+    TAny* aObjPtr, 
+    TPtrC aStrPtr, 
+    TAknTasHookObjectType aObjType )
+    {    
+    if ( iTasHookStoringEnabled )
+        {
+        CAknTasObjectInfo* objInfo = new ( ELeave ) CAknTasObjectInfo();
+        CleanupStack::PushL( objInfo );
+        objInfo->ConstructL( aObjPtr, aObjType );
+        CleanupStack::Pop( objInfo );
+        CAknTasClassInfo* classInfo = new ( ELeave ) CAknTasClassInfo();
+        CleanupStack::PushL( classInfo );
+        classInfo->ConstructL( aStrPtr );
+        CleanupStack::Pop( classInfo );
+        
+        if ( iObjectInfoArray->Count() <= 0 )
+            {
+            objInfo->AddL( classInfo );
+            iObjectInfoArray->AppendL( objInfo );
+            return;
+            }
+                
+        TIdentityRelation<CAknTasObjectInfo> matcher( CAknTasObjectInfo::MatchByControl );
+        TInt position = iObjectInfoArray->Find( objInfo, matcher );
+        if ( position != KErrNotFound )
+            {
+            delete objInfo;
+            objInfo = ( *iObjectInfoArray )[position];
+            }
+        else
+            {
+            iObjectInfoArray->AppendL( objInfo );
+            }
+        objInfo->AddL( classInfo );
+        }
+    }
+    
+EXPORT_C CAknTasObjectInfo* CAknTasHook::Get( TAny* aObjPtr )
+    {
+    CAknTasHook* mePtr = Self();
+    if ( !mePtr->iTasHookingEnabled )
+        {
+        return NULL;
+        }
+    
+    if ( mePtr )
+        {
+        return mePtr->GetInfo( aObjPtr );
+        }
+        
+    return NULL;
+    }
+    
+CAknTasObjectInfo* CAknTasHook::GetInfo( TAny* aObjPtr )
+    {
+    CAknTasObjectInfo* objInfo = NULL;
+    TRAPD( err,
+            objInfo = new ( ELeave ) CAknTasObjectInfo();
+            CleanupStack::PushL( objInfo );
+            objInfo->ConstructL( aObjPtr ) );
+            CleanupStack::Pop( objInfo );
+    if ( err )
+        {
+        if ( objInfo )
+            {
+            CleanupStack::PopAndDestroy( objInfo );
+            }
+        return NULL;
+        }
+    
+    TIdentityRelation<CAknTasObjectInfo> matcher( CAknTasObjectInfo::MatchByControl );
+    TInt position = iObjectInfoArray->Find( objInfo, matcher );
+    delete objInfo;
+    if ( position != KErrNotFound )
+        {
+        return ( *iObjectInfoArray )[position];
+        }
+    else
+        {
+        return NULL;
+        }
+    }
+              
+TBool CAknTasHook::ExistsL( TAny* aObjPtr )
+    {    
+    CAknTasHook* mePtr = InstanceL();
+    return mePtr->InfoExistsL( aObjPtr );
+    }
+    
+TBool CAknTasHook::InfoExistsL( TAny* aObjPtr )
+    {
+    if ( iObjectInfoArray->Count() <= 0 )
+        {
+        return EFalse;
+        }
+    
+    CAknTasObjectInfo* objInfo = new ( ELeave ) CAknTasObjectInfo();
+    CleanupStack::PushL( objInfo );
+    objInfo->ConstructL( aObjPtr );
+    CleanupStack::Pop( objInfo );
+    
+    TIdentityRelation<CAknTasObjectInfo> matcher( CAknTasObjectInfo::MatchByControl );
+    TInt position = iObjectInfoArray->Find( objInfo, matcher );
+    delete objInfo;
+    if ( position != KErrNotFound )
+        {
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }    
+    }
+    
+EXPORT_C void CAknTasHook::Remove( TAny* aObjPtr )
+    {
+    CAknTasHook* mePtr = Self();
+    if ( mePtr )
+        {
+        TInt err( KErrNone );
+        TRAP( err, mePtr->RemoveInfoL( aObjPtr ) );
+        }
+    }
+    
+void CAknTasHook::RemoveInfoL( TAny* aObjPtr )
+    {
+    if ( iTasHookStoringEnabled )
+        {
+        if ( iObjectInfoArray->Count() <= 0 )
+            {
+            return;
+            }
+        
+        CAknTasObjectInfo* objInfo = new ( ELeave ) CAknTasObjectInfo();
+        CleanupStack::PushL( objInfo );
+        objInfo->ConstructL( aObjPtr );
+        CleanupStack::Pop( objInfo );
+            
+        TIdentityRelation<CAknTasObjectInfo> matcher( CAknTasObjectInfo::MatchByControl );
+        TInt position = iObjectInfoArray->Find( objInfo, matcher );
+        delete objInfo;
+        if ( position != KErrNotFound )
+            {
+            objInfo = ( *iObjectInfoArray )[position];
+            iObjectInfoArray->Remove( position );
+            delete objInfo;
+            }
+        }
+    }
+
+EXPORT_C RPointerArray<CAknTasObjectInfo>* CAknTasHook::GetAll()
+    {
+    if ( !iTasHookingEnabled )
+        {
+        return NULL;
+        }
+    return iObjectInfoArray;
+    }
+
+EXPORT_C void CAknTasHook::GetAknUiLC( MTasObject& aParentApplication )
+    {
+    if ( !iTasHookingEnabled )
+        {
+        return;
+        }
+    
+    TInt numObjects = iObjectInfoArray->Count();
+        
+    for ( TInt i = 0; i < numObjects; i++ )
+        {
+        CAknTasObjectInfo* objInfo = ( *iObjectInfoArray )[i];
+        
+        if ( objInfo->IsA( _L( "CAknBatteryStrength" ) ) )
+            {
+            if ( !CheckSanityL( ( CCoeControl* ) objInfo->GetControl() ) )
+                {
+                continue;
+                }
+            CAknBatteryStrength* battery = 
+                static_cast<CAknBatteryStrength*>( objInfo->GetControl() );
+            if ( battery )
+                {
+                MTasObject& tasObj = aParentApplication.AddObjectL();
+                //tasObj.AddAttributeL( _L( "Id" ), objInfo->iControlKey );
+                tasObj.SetNameL( _L( "CAknBatteryStrength" ) );
+                tasObj.SetTypeL( _L( "indicator" ) );
+                tasObj.SetIdL( objInfo->iControlKey );
+                tasObj.AddAttributeL( _L( "Level" ), battery->BatteryLevel() );
+                tasObj.AddAttributeL( _L( "Recharging" ), battery->Recharging() );
+                AddCommonCoeInfoL( ( CCoeControl* ) objInfo->GetControl(), tasObj );
+                }
+            }
+        else if ( objInfo->IsA( _L( "CAknSignalStrength" ) ) )
+            {
+            if ( !CheckSanityL( ( CCoeControl* )objInfo->GetControl() ) )
+                {
+                continue;
+                }
+            CAknSignalStrength* signal = 
+                static_cast<CAknSignalStrength*>( objInfo->GetControl() );
+            if ( signal )
+                {                
+                MTasObject& tasObj = aParentApplication.AddObjectL();
+                //tasObj.AddAttributeL( _L( "Id" ), objInfo->iControlKey );
+                tasObj.SetNameL( _L( "CAknSignalStrength" ) );
+                tasObj.SetTypeL( _L( "indicator" ) );
+                tasObj.SetIdL( objInfo->iControlKey );
+                tasObj.AddAttributeL( _L( "Level" ), signal->SignalLevel() );
+                AddCommonCoeInfoL( ( CCoeControl* ) objInfo->GetControl(), tasObj );
+                }
+            }
+        }
+    }
+
+void CAknTasHook::AddCommonCoeInfoL( CCoeControl* aObjPtr, MTasObject& aObjectInfo )
+    {
+    //add positional details
+    TRect absoluteRect( 0, 0, 0, 0 );
+    if ( aObjPtr->OwnsWindow() )
+        {
+        RDrawableWindow* window = aObjPtr->DrawableWindow();
+        if ( window )
+            {
+            TRect tempRect( window->AbsPosition(), window->Size() );
+            absoluteRect = tempRect;
+            }
+        }
+    else
+        {
+        TRect tempRect( aObjPtr->PositionRelativeToScreen(), aObjPtr->Size() );
+        absoluteRect = tempRect;
+        }
+    
+    aObjectInfo.AddAttributeL( _L( "X" ), absoluteRect.iTl.iX );
+    aObjectInfo.AddAttributeL( _L( "Y" ), absoluteRect.iTl.iY );
+    aObjectInfo.AddAttributeL( _L( "Width" ), absoluteRect.Width() );
+    aObjectInfo.AddAttributeL( _L( "Height" ), absoluteRect.Height() );
+    
+    //some general details
+    aObjectInfo.AddAttributeL( _L( "Visible" ), ( aObjPtr->IsVisible()? _L( "TRUE" ) : _L( "FALSE" ) ) );
+    aObjectInfo.AddAttributeL( _L( "Focused" ), ( aObjPtr->IsFocused()? _L( "TRUE" ): _L( "FALSE" ) ) );
+    aObjectInfo.AddAttributeL( _L( "Dimmed" ), ( aObjPtr->IsDimmed()? _L( "TRUE" ): _L( "FALSE" ) ) );
+    aObjectInfo.AddAttributeL( _L( "HasBorder" ), ( aObjPtr->HasBorder()? _L( "TRUE" ): _L( "FALSE" ) ) );
+    }
+
+void CAknTasHook::HandleNotifyInt( TUint32 aId, TInt aNewValue )
+    {
+    if ( aId == KTasHooking )
+        {
+        if ( aNewValue == KTasHookingOn && !iTasHookingEnabled )
+            {
+            TRAPD( errorCreate, iTasPlugin = CAknTasPluginInterface::NewL() );
+            if ( errorCreate != KErrNone )
+                {
+                iTasHookingEnabled = EFalse;
+                return;
+                }
+            TRAPD( errorSet, iTasPlugin->SetHookInterfaceL( InstanceL() ) );
+            if ( errorSet != KErrNone )
+                {
+                delete iTasPlugin;
+                iTasPlugin = NULL;
+                iTasHookingEnabled = EFalse;
+                return;
+                }
+            iTasHookingEnabled = ETrue;
+            }
+        else if ( aNewValue == KTasHookingOff && iTasHookingEnabled )
+            {
+            delete iTasPlugin;
+            iTasPlugin = NULL;
+            iTasHookingEnabled = EFalse;
+            }
+        else
+            {
+            // Invalid value
+            }
+        }
+    else if ( aId == KTasHookStoring )
+        {
+        if ( aNewValue == KTasHookingOn )
+            {
+            iTasHookStoringEnabled = ETrue;
+            }
+        else if ( aNewValue == KTasHookingOff )
+            {
+            iTasHookStoringEnabled = EFalse;
+            }
+        else
+            {
+            // Invalid value
+            }
+        }
+    else
+        {
+        // Wrong key
+        }
+    }
+
+TBool CAknTasHook::CheckSanityL( CCoeControl* aControl )
+    {
+    // check the sanity of the object
+    if ( !aControl || 
+         !aControl->DrawableWindow() || 
+         !aControl->ControlEnv() ||
+         !aControl->IsVisible() )
+        {
+        return EFalse;
+        }
+    
+    if ( !iTasPlugin->IsControlVisible( *aControl ) )
+        {
+        return EFalse;
+        }
+    
+    return ETrue;
+    }
+
+// End of File