idlehomescreen/xmluicontroller/src/contentrenderer.cpp
changeset 0 f72a12da539e
child 4 4d54b72983ae
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/idlehomescreen/xmluicontroller/src/contentrenderer.cpp	Thu Dec 17 08:40:49 2009 +0200
@@ -0,0 +1,1688 @@
+/*
+* Copyright (c) 2005-2007 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:  Content renderer implementation
+*
+*/
+
+// System includes
+#include    <e32hashtab.h>
+#include    <utf.h>
+#include    <gulicon.h>
+
+// User includes
+
+#include    "contentrenderer.h"
+#include    "appui.h"
+#include    "activetransactionstack.h"
+#include    "transactionfactoryimpl.h"
+#include    "mtransaction.h"
+#include    "mtransactionelement.h"
+#include    "aixmluiutils.h"
+#include    "xmluicontroller.h"
+#include    "xmlnodeidgenerator.h"
+#include    "aixmluiconstants.h"
+#include    "aifweventhandler.h"
+#include    "databuffertransactionelement.h"
+#include    "newstickercallbackhandler.h"
+#include    "newstickertransactionelement.h"
+#include    "csspropertymap.h"
+#include    "policyevaluator.h"
+#include    "debug.h"
+#include    "xnuiengineappif.h"
+#include    "xnnodeappif.h"
+#include    "xnproperty.h"
+#include    "mxncomponentinterface.h"
+#include    "xntext.h"
+#include    "xnbitmap.h"
+#include    "xntype.h"
+#include    "xnmenuadapter.h"
+#include    "xnlistquerydialogadapter.h"
+#include    "mxncomponentinterface.h"
+#include    "aistrcnv.h"
+#include    "contentprioritymap.h"
+#include    "ainativeuiplugins.h"
+
+using namespace AiXmlUiController;
+using namespace AiUiDef::xml;
+using namespace XnTextInterface;
+using namespace XnImageInterface;
+
+namespace
+    {
+    typedef RPointerArray<CXnNodeAppIf> RXnNodeArray;
+
+    /**
+     * Gets content item iterator.
+     *
+     * @param aPlugin plugin to fetch the iterator
+     * @param aContentType type of iterator (content/resource/event)
+     * @return the iterator
+     * @leave KErrNotSupported if plugin does not provide iterator
+     */ 
+    static MAiContentItemIterator& ContentItemIteratorL( MAiPropertyExtension& aPlugin,
+                                                         TInt aContentType )
+        {
+        MAiContentItemIterator* iter =
+            static_cast< MAiContentItemIterator* >( aPlugin.GetPropertyL( aContentType ) );
+
+        if ( !iter )
+            {
+            User::Leave( KErrNotSupported );
+            }
+
+        return *iter;
+        }
+
+    /**
+     * Gets the content priority associated in the property element.
+     *
+     * @param aPropertyElement the property element
+     * @return priority value or KErrNotFound for non-prioritized element
+     */
+    TInt GetContentPriority( CXnNodeAppIf& aPropertyElement )
+        {
+        TInt32 priority( KErrNotFound );
+        
+        const TDesC8* name = PropertyValue( aPropertyElement,
+                                            property::KName );
+                                            
+        
+        if ( name && *name == name::KPriority )
+            {
+            const TDesC8* value = PropertyValue( aPropertyElement,
+                                                 property::KValue );
+            if ( value )
+                {
+                AiUtility::ParseInt( priority, *value );
+                }
+            }
+            
+        return priority;
+        }
+    
+    /**
+     * Remove elements from array which do not contain priority or priority is not lower than
+     * the given value.
+     * 
+     * @param aElements array of elements
+     * @param aLastPriority upper bound of priority value (excluded from the array)
+     */
+    void RemoveNonPriorityElements( RPointerArray< CXnNodeAppIf>& aElements,
+                                    TInt aLastPriority )
+        {
+        //  Remove non priority elements and higher priority elements
+
+        TInt elementCount = aElements.Count();    
+        for ( TInt i = 0; i < elementCount; )
+            {
+            CXnNodeAppIf* current = aElements[i];
+            
+            // Check name attribute
+            const TDesC8* name = PropertyValue( *current, property::KName );
+            
+            if ( !name || *name != name::KPriority )
+                {
+                // Remove current
+                aElements.Remove( i );
+                --elementCount;
+                }
+            else
+                {
+                // Check current priority
+                const TDesC8* value = PropertyValue( *current, property::KValue );
+                
+                if ( !value ) // value not present
+                    {
+                    aElements.Remove( i );
+                    --elementCount;
+                    continue;
+                    }
+                
+                TInt32 currentPriority( KErrNotFound );
+                if ( AiUtility::ParseInt( currentPriority, *value ) != KErrNone )
+                    {
+                    // value is not integer
+                    aElements.Remove( i );
+                    --elementCount;
+                    continue;
+                    }
+                    
+                if ( currentPriority < aLastPriority )
+                    {
+                    // Keep element and iterate further
+                    ++i;
+                    }
+                else
+                    {
+                    // priority is too high
+                    aElements.Remove( i );
+                    --elementCount;
+                    }
+                }
+            }
+        }
+    
+    /**
+     * Descending priority order for prioritized content selectors.
+     *
+     * @param aNode1 First node to compare
+     * @param aNode2 Second node to compare
+     * @return 0 nodes have equal priority
+     * @return >0 aNode1 has lower priority
+     * @return <0 aNode2 has lower priority
+     */
+    TInt DescendingPriorityOrder( const CXnNodeAppIf& aNode1,
+                                  const CXnNodeAppIf& aNode2 )
+        {
+        // Array content has been validated, so no checks are needed
+        const TDesC8* value1 = PropertyValue( aNode1,
+                                              property::KValue );
+        
+        const TDesC8* value2 = PropertyValue( aNode2,
+                                              property::KValue );
+        
+        TInt32 priority1( KErrNotFound );
+        AiUtility::ParseInt( priority1, *value1 );
+        
+        TInt32 priority2( KErrNotFound );
+        AiUtility::ParseInt( priority2, *value2 );
+        
+        if ( priority1 == priority2 )
+            {
+            return 0;
+            }
+            
+        return ( priority1 < priority2 ) ? 1 : -1;
+        }
+    
+    /**
+     * Removes duplicate entries in content change array
+     */
+    void RemoveDuplicateContentChangesL( RAiPolicyElementArray& aArray )
+        {
+        for ( TInt i = 0; i < aArray.Count(); ++i )
+            {
+            HBufC* id = PropertyValueL( aArray[i].Target(), 
+                                            AiUiDef::xml::property::KId );
+            if ( id )
+                {
+                CleanupStack::PushL( id );
+                for ( TInt j = i; j < aArray.Count(); ++j )
+                    {
+                    HBufC* id2 = PropertyValueL( aArray[j].Target(), 
+                                                           AiUiDef::xml::property::KId );
+                    if ( id2)
+                        {
+                        CleanupStack::PushL( id2 );
+                        // Same id and same policy
+                        if ( i != j &&
+                             id->Compare( *id2 ) == 0 && 
+                             ( aArray[i].Policy().Compare( aArray[j].Policy()) == 0) 
+                                )
+                            {
+                            aArray.Remove( j );
+                            --j;
+                            }
+                        }
+                    CleanupStack::PopAndDestroy( id2 );
+                    
+                    }
+                CleanupStack::PopAndDestroy( id );
+                }
+            }
+        }
+    /**
+     * Cleanup item for cleanup of TPtrHashMapIter
+     */            
+    class TMapCleanupItem
+        {
+    public:
+        
+        TMapCleanupItem( TPtrHashMapIter< TDesC, TInt >& aIterator );
+        
+        /**
+         * Removes the pointers in the map and deletes the objects
+         * referenced by the pointers.
+         */ 
+        void Release();
+                
+    private:
+            
+        TPtrHashMapIter< TDesC, TInt > iIterator;
+        
+        };
+
+    /**
+     * Helper to handle cleanup of map iterator
+     * @param aMapCleanupItem 
+     */
+    void CleanupRelease( TAny* aMapCleanupItem )
+        {
+        if ( aMapCleanupItem )
+            {
+            static_cast< TMapCleanupItem* >( aMapCleanupItem )->Release();
+            }
+        }
+
+    /**
+     * Helper to push map iterator into cleanup stack.
+     *
+     * @param aCleanupItem item to push into cleanup stack
+     **/
+    void CleanupReleasePushL( TMapCleanupItem& aCleanupItem )
+        {
+        CleanupStack::PushL( TCleanupItem( CleanupRelease,
+                                           &aCleanupItem ) );
+        }
+
+    
+    }
+
+TMapCleanupItem::TMapCleanupItem( TPtrHashMapIter< TDesC, TInt >& aIterator )
+    : iIterator( aIterator )
+    {
+    }
+
+void TMapCleanupItem::Release()
+    {
+    // Delete current key and value
+    const TDesC* key = iIterator.CurrentKey();
+    const TInt* value = iIterator.CurrentValue();
+    
+    delete key;
+    delete value;
+    
+    // Remove mapping from the map.
+    iIterator.RemoveCurrent();
+    }
+
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+CContentRenderer::CContentRenderer( CAppUi& aAppUi )
+    : iAppUi( aAppUi )
+    {
+    }
+
+void CContentRenderer::ConstructL()
+    {
+    iContentPriorityMap = AiUtility::CContentPriorityMap::NewL();
+    iPropertyMap = CCssPropertyMap::NewL();
+    iFactory = CTransactionFactoryImpl::NewL(*iContentPriorityMap,
+                                             *iPropertyMap);
+    iStack = CActiveTransactionStack::NewL();
+    iNodeIdGenerator = CXmlNodeIdGenerator::NewL();
+    iTimer = CPeriodic::NewL( CActive::EPriorityStandard );
+    iPolicyEvaluator = CPolicyEvaluator::NewL();
+    }
+
+CContentRenderer* CContentRenderer::NewL( CAppUi& aAppUi )
+    {
+    CContentRenderer* self = new( ELeave ) CContentRenderer( aAppUi );
+
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+
+    return self;
+    }
+
+CContentRenderer::~CContentRenderer()
+    {
+    delete iPolicyEvaluator;
+    
+    if ( iTimer )
+        {
+        iTimer->Cancel();
+        delete iTimer;
+        }
+        
+    delete iNodeIdGenerator;
+    
+    if ( iStack )
+        {
+        while ( !iStack->IsEmpty() )
+            {
+            MTransaction* tr = iStack->Pop();
+            iFactory->ReleaseTransaction( tr );
+            }
+
+        delete iStack;
+        }
+    
+    delete iFactory;
+    
+    iRefreshableUiElements.ResetAndDestroy();
+    
+    delete iNTClass;
+    
+    delete iPropertyMap;
+    
+    delete iContentPriorityMap;
+    delete iCallbackHandler;
+    }
+
+void CContentRenderer::SetEventHandler( MAiFwEventHandler& aFwEventHandler )
+    {
+    iFwEventHandler = &aFwEventHandler;
+    }
+
+void CContentRenderer::Reset()
+    {
+    iContentPriorityMap->Reset();
+    iPropertyMap->Reset();
+    }
+
+void CContentRenderer::CleanPluginFromUi( MAiPropertyExtension& aPlugin )
+    {
+    // Create transaction to clean UI
+    TInt txId = reinterpret_cast< TInt >( &aPlugin );
+    
+    TBool txCreated = ( StartTransaction( txId ) == KErrNone );
+    
+    // Clean plugin
+    TRAPD( cleanError, CleanPluginFromUiL( aPlugin ) );
+    
+    // Commit transaction
+    if ( txCreated )
+        {
+        if (cleanError )
+            {
+            CancelTransaction( txId );
+            }
+        else
+            {
+            Commit( txId );
+            }
+        }
+    }
+
+TInt CContentRenderer::StartTransaction( TInt aTxId )
+    {
+    __PRINT(__DBG_FORMAT("\t[I]\tXML UI: Start transaction id=%d"), aTxId);
+    __HEAP("XML UI: Start transaction");
+    __TICK("XML UI: Start transaction");
+    TRAPD( error, DoStartTransactionL( aTxId ) );
+
+    if ( error )
+        {
+        SetImmediateMode( ETrue );
+        }
+
+    return error;
+    }
+
+TInt CContentRenderer::Commit( TInt aTxId )
+    {
+    // Remove transaction with aTxId from stack
+    MTransaction* tr = iStack->Remove( aTxId );
+
+    if ( tr )
+        {
+        // Commit transaction        
+        RPropertyHashMap propertyHashMap;
+        
+        TBool layoutChanged( EFalse );
+        
+        TRAPD( error, tr->CommitL( layoutChanged, propertyHashMap ) );
+        if( error == KErrNone )
+            {
+            TRAP_IGNORE( SetPropertyArraysL( propertyHashMap ) );
+            }
+        propertyHashMap.Close();
+
+        __TICK("XML UI: Commit transaction");
+        __HEAP("XML UI: Commit transaction");
+        __PRINT(__DBG_FORMAT("\t[I]\tXML UI: Commit transaction id=%d"), aTxId);
+       
+        StartContentRefresh();
+        
+        TRAP_IGNORE
+            (
+            iAppUi.UiEngineL()->RenderUIL();                                  //jtm+++
+            ProcessContentChangesL( *tr );
+            );
+                
+        
+        iFactory->ReleaseTransaction( tr );  
+        
+        return error;
+        }
+        
+    return KErrNotSupported;
+    }
+
+void CContentRenderer::ProcessContentChangesL( MTransaction& aTr )
+    {
+    TDblQueIter<CTransactionElement> iter = aTr.ElementIter();
+    RAiPolicyElementArray contentChangedArray;
+    CleanupClosePushL( contentChangedArray );
+
+    while ( iter )
+          {
+          CTransactionElement* element = iter++;
+          CXnNodeAppIf& target = element->Target();
+          
+          // Find own and parents policy/ContentChanged nodes 
+          iPolicyEvaluator->EvaluateContentChangedPolicyL( target, 
+                  contentChangedArray);
+
+          iPolicyEvaluator->EvaluateContentChangedPolicyL( *(target.ParentL()), 
+                  contentChangedArray);
+          }
+       
+    ::RemoveDuplicateContentChangesL( contentChangedArray );
+        
+    for ( TInt i = 0; i < contentChangedArray.Count(); ++i )
+        {
+        ProcessContentChangeL( contentChangedArray[i] );
+        }
+    CleanupStack::PopAndDestroy();
+    }
+
+void CContentRenderer::ProcessContentChangeL( TAiPolicyElement& aElement )
+    {
+    const TDesC8* id = PropertyValue( aElement.Target(), 
+                                AiUiDef::xml::property::KId );
+    if ( id )
+        {
+        CXnNodeAppIf* targetNode = FindNodeByIdL( *id, aElement.Target().Namespace() );
+        if ( targetNode )
+            {                     
+            if ( aElement.Policy() == AiUiDef::xml::value::KShowTooltips )
+                {
+                targetNode->ShowTooltipsL();
+                }                   
+            }        
+        }
+    }
+
+TInt CContentRenderer::CancelTransaction( TInt aTxId )
+    {
+    // Remove transaction with aTxId from stack
+    MTransaction* tr = iStack->Remove( aTxId );
+
+    if ( tr )
+        {
+        // Release transaction to factory
+        __TICK("XML UI: Cancel transaction");
+        __HEAP("XML UI: Cancel transaction");
+        __PRINT(__DBG_FORMAT("\t[I]\tXML UI: Cancel transaction id=%d"), aTxId);
+
+        iFactory->ReleaseTransaction( tr );
+
+        return KErrNone;
+        }
+
+    return KErrNotSupported;
+    }
+
+TBool CContentRenderer::CanPublish( MAiPropertyExtension& aPlugin,
+                                    TInt aContent,
+                                    TInt aIndex )
+    {
+    TInt error( KErrNone );
+    TInt retval( KErrNone );
+    __PRINTS("*** UC: Init - Content Validation ***");
+	__TIME("UC: Content Validation",
+        TRAP( error, retval = CanPublishL( aPlugin, aContent, aIndex ) );
+        );
+    __HEAP("UC: Content Validation");
+    __PRINTS("*** UC: Done - Content Validation ***");
+
+    return ( error == KErrNone && retval == KErrNone );
+    }
+
+TInt CContentRenderer::Publish( MAiPropertyExtension& aPlugin,
+                                TInt aContent,
+                                TInt aResource,
+                                TInt aIndex )
+    {
+	TInt error( KErrNone );
+	TInt retval( KErrNone );
+	__PRINTS("*** UC: Init - Content Publishing (Resource) ***");
+	__TIME("UC: Content Publishing (Resource)",
+    	TRAP( error, retval = DoPublishL( aPlugin, aContent, aResource, aIndex ) );
+    );
+    __HEAP("UC: Content Publishing (Resource)");
+    __PRINTS("*** UC: Done - Content Publishing (Resource) ***");
+
+    if( !error && retval )
+        {
+        error = retval;
+        }
+    
+    return error;
+    }
+
+TInt CContentRenderer::Publish( MAiPropertyExtension& aPlugin,
+                                TInt aContent,
+                                const TDesC16& aText,
+                                TInt aIndex )
+    {
+    TInt error( KErrNone );
+    TInt retval( KErrNone );
+    
+    __PRINTS("*** UC: Init - Content Publishing (Value-Text) ***");
+   	__TIME("UC: Content Publishing (Value-Text)",
+    	TRAP( error, retval = DoPublishL( aPlugin, aContent, aText, aIndex ) );
+    );
+    __HEAP("UC: Content Publishing (Value-Text)");
+    __PRINTS("*** UC: Done - Content Publishing (Value-Text) ***");
+
+    if( !error && retval )
+        {
+        error = retval;
+        }
+
+    return error;
+    }
+
+TInt CContentRenderer::Publish( MAiPropertyExtension& aPlugin,
+                                TInt aContent,
+                                const TDesC8& aBuf,
+                                TInt aIndex )
+    {
+    TInt error( KErrNone );
+    TInt retval( KErrNone );
+    
+    __PRINTS("*** UC: Init - Content Publishing (Value-Buf) ***");
+    __TIME("UC: Content Publishing (Value-Buf)",
+    	TRAP( error, retval = DoPublishL( aPlugin, aContent, aBuf, aIndex ) );
+    )
+    __HEAP("UC: Content Publishing (Value-Buf)");
+    __PRINTS("*** UC: Done - Content Publishing (Value-Buf) ***");
+
+    if( !error && retval )
+        {
+        error = retval;
+        }
+    
+    return error;
+    }
+
+TInt CContentRenderer::Publish( MAiPropertyExtension& aPlugin,
+                                TInt aContent,
+                                RFile& aFile,
+                                TInt aIndex )
+    {
+    TInt error( KErrNone );
+    TInt retval( KErrNone );
+    	
+	__PRINTS("*** UC: Init - Content Publishing (Value-RFile) ***");
+    __TIME("UC: Content Publishing (Value-RFile)",
+    	TRAP( error, retval = DoPublishL( aPlugin, aContent, aFile, aIndex ) );
+    );
+    __HEAP("UC: Content Publishing (Value-RFile)");
+    __PRINTS("*** UC: Done - Content Publishing (Value-RFile) ***");
+
+    if( !error && retval )
+        {
+        error = retval;
+        }
+    
+    return error;
+    }
+
+TInt CContentRenderer::Clean( MAiPropertyExtension& aPlugin, TInt aContent, TInt aIndex )
+    {
+    TInt error( KErrNone );
+    TInt retval( KErrNone );
+            
+    __PRINTS("*** UC: Init - Content Publishing (Clean) ***");
+    __TIME("UC: Content Publishing (Clean)",
+    	TRAP( error, retval = DoCleanL( aPlugin, aContent, aIndex ) );
+    );
+    __HEAP("UC: Content Publishing (Clean)");
+    __PRINTS("*** UC: Done - Content Publishing (Clean) ***");
+
+    if( !error && retval )
+        {
+        error = retval;
+        }
+    
+    return error;
+    }
+
+TAny* CContentRenderer::Extension( TUid /*aUid*/ )
+    {
+    // No extensions supported
+    return NULL;
+    }
+
+TBool CContentRenderer::RequiresSubscription( 
+    const TAiPublisherInfo& aPublisherInfo ) const
+    {
+    if ( aPublisherInfo.iNamespace == KNativeUiNamespace )
+        {
+        // Not targeted to this content renderer
+        return EFalse;
+        }
+        
+    return ETrue;
+    }
+
+void CContentRenderer::DoStartTransactionL( TInt aTxId )
+    {
+    MTransaction* tr = iFactory->CreateTransactionL( aTxId );
+    iStack->Push(tr);
+    SetImmediateMode(EFalse);
+    }
+
+TInt CContentRenderer::CanPublishL( MAiPropertyExtension& aPlugin,
+                                    TInt aContent,
+                                    TInt aIndex )
+    {
+    // Get content item for aContent
+    MAiContentItemIterator& iter( 
+            ContentItemIteratorL( aPlugin, EAiPublisherContent ) );
+    
+    const TAiContentItem& item( iter.ItemL( aContent ) );
+
+    // Lookup ui element
+    const TDesC& nodeId( iNodeIdGenerator->ContentNodeIdL( aPlugin, item ) );
+
+    CXnNodeAppIf* property( FindNodeByClassL( nodeId, aIndex, 
+                            aPlugin.PublisherInfoL()->iNamespace ) ); 
+ 
+    if( !property )
+        {
+        return KErrNotFound;
+        }
+    
+    // Check content priority
+    TInt priority( GetContentPriority( *property ) );
+
+    CXnNodeAppIf* target( property->ParentL() );
+    
+    if( !target )
+        {
+        return KErrNotSupported;
+        }
+
+    if ( !AllowPublishByPriority( *target, priority ) )
+        {
+        return KErrAccessDenied;        
+        }
+
+    // Check if content type is supported by target
+    const TDesC8& contentType( ContentType( item ) );
+
+    if ( !iFactory->IsSupported( *target, contentType ) &&
+          target->Type()->Type() != XnPropertyNames::listquerydialog::KListQueryDialog )
+        {
+        return KErrNotSupported;
+        }
+    
+    return KErrNone;
+    }
+
+TInt CContentRenderer::DoPublishL( MAiPropertyExtension& aPlugin,
+                                   TInt aContent,
+                                   TInt aResource,
+                                   TInt aIndex )
+    {
+    TAiPublisherInfo *info = static_cast<TAiPublisherInfo*>(aPlugin.GetPropertyL( EAiPublisherInfo ));
+    if (!info)
+        {
+        return KErrNotFound;
+        }
+    // Read ref value.
+    MAiContentItemIterator& refIter( ContentItemIteratorL( aPlugin, EAiPublisherResources ) );
+    const TAiContentItem& ref( refIter.ItemL( aResource ) );
+
+    const TDesC8& refType( ContentType( ref ) );
+
+    // Resolve source node
+    const TDesC& nodeId = iNodeIdGenerator->ResourceNodeIdL(aPlugin, ref);
+    HBufC8* nodeId8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L(nodeId);
+    CleanupStack::PushL(nodeId8);
+    CXnNodeAppIf* source = NULL;
+    __TIME_MARK(xmlOverhead);
+    source = FindNodeByIdL( *nodeId8, info->iNamespace );
+    __TIME_ENDMARK("XML UI: Lookup node by id", xmlOverhead);
+    __PRINT(__DBG_FORMAT("\t[I]\tXML UI: Lookup node by id=%S"), &nodeId);
+    
+    CleanupStack::PopAndDestroy(nodeId8);
+    
+    // Fetch content id
+    MAiContentItemIterator& iter = ContentItemIteratorL( aPlugin, EAiPublisherContent );
+    const TAiContentItem& item = iter.ItemL( aContent );
+
+    const TDesC& targetId = iNodeIdGenerator->ContentNodeIdL(aPlugin, item);
+
+    TInt retval( KErrNotSupported );
+
+    // Check types
+    if ( refType == KContentTypeText )
+        {
+        // Fetch text
+        const TDesC8& text = source->GetPCData();
+        
+        // Delegate to data publishing function
+        retval = PublishDataL( aPlugin,
+                               targetId,
+                               text,
+                               refType,
+                               aIndex,
+                               source );
+        }
+    else if ( refType.Find( KContentTypeImage ) != KErrNotFound )
+        {
+        // Fetch icon
+        CGulIcon* icon = LoadIconLC( *source ); 
+        
+       // Delegate to icon publishing function
+        retval = PublishIconL( aPlugin,
+                               targetId,
+                               icon,
+                               aIndex,
+                               source );
+        
+        CleanupStack::Pop( icon );
+        }
+    
+    return retval;
+    }
+
+TInt CContentRenderer::DoPublishL( MAiPropertyExtension& aPlugin,
+                                   TInt aContent,
+                                   const TDesC16& aText,
+                                   TInt aIndex )
+    {
+    // Resolve content item
+    MAiContentItemIterator& iter( 
+            ContentItemIteratorL( aPlugin, EAiPublisherContent ) );
+    
+    const TAiContentItem& item( iter.ItemL( aContent ) );
+
+    const TDesC8& type( ContentType( item ) );
+
+    if ( type == KContentTypeText )
+        {
+        // Find ui element
+        const TDesC& nodeId = iNodeIdGenerator->ContentNodeIdL( aPlugin, item );
+
+        __TIME_MARK(xmlOverhead);
+
+        CXnNodeAppIf* property( FindNodeByClassL( nodeId, aIndex, 
+                                                  aPlugin.PublisherInfoL()->iNamespace ) );
+
+        if( !property )
+            {
+            return KErrNotFound;
+            }
+        
+        TInt priority( GetContentPriority( *property ) );
+        
+        __TIME_ENDMARK("XML UI: Lookup node by class", xmlOverhead);
+    	__PRINT(__DBG_FORMAT("\t[I]\tXML UI: Lookup node by class=%S"), &nodeId);
+
+        //Navigate to parent
+        CXnNodeAppIf* target( property->ParentL() );
+
+        if( !target )
+            {
+            return KErrNotSupported;
+            }
+        
+        // Check priority
+        if ( AllowPublishByPriority( *target, priority ) )
+            {
+            // Check if target is newsticker
+            MTransactionElement* element( NULL );
+            
+            if ( IsParentNewsticker( *target ) )
+                {
+                // Register callback interface for newsticker
+                CXnNodeAppIf *parent( target->ParentL() );
+                
+                if( !parent )
+                    {
+                    return KErrNotFound;
+                    }
+                                
+                RegisterNewstickerCallbackInterfaceL( *parent );
+                
+                const TAiPublisherInfo* info( aPlugin.PublisherInfoL() );
+                
+                if ( info )
+                    {
+                    iNTPublisher.Set( info->iName );
+                    iNTClass = AiUtility::CopyToBufferL( iNTClass, nodeId );
+                    }
+                
+                element = iFactory->CreateNewsTickerTransactionElementL( *target,
+                                                                    aText,
+                                                                    priority, 
+                                                                    aIndex );
+                }
+            else if( target->Type()->Type() == 
+                     XnListQueryDialogInterface::MXnListQueryDialogInterface::Type())
+                {
+                // Get the data interface for dialog and publish data
+                XnListQueryDialogInterface::MXnListQueryDialogInterface* listQuery( NULL );
+                XnComponentInterface::MakeInterfaceL( listQuery, *target );
+                LeaveIfNull( listQuery, KErrNotSupported );
+                listQuery->ReplaceItemL( aText, aIndex -1 );// plugins publish ordinals not indexes
+                return KErrNone;
+                }
+            else
+                {
+                // Create transaction element for text
+                // Not put to cleanupstack, because element is from our pool!
+                element = iFactory->CreateTextTransactionElementL( *target,
+                                                                    aText,
+                                                                    priority );
+                }
+            
+            iPolicyEvaluator->EvaluateContentPolicyL( *target,
+                                                      element->PolicyArray() );
+            iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+                                                         element->PolicyArray() );
+
+            ProcessTransactionElementL( element );
+            }
+        else
+            {
+            return KErrAccessDenied;            
+            }
+        }
+    else
+        {
+        return KErrNotSupported;
+        }
+    
+    return KErrNone;
+    }
+
+TInt CContentRenderer::DoPublishL( MAiPropertyExtension& aPlugin,
+                                   TInt aContent,
+                                   const TDesC8& aBuf,
+                                   TInt aIndex )
+    {
+    // resolve content item
+    MAiContentItemIterator& iter( 
+            ContentItemIteratorL( aPlugin, EAiPublisherContent ) );
+    
+    const TAiContentItem& item( iter.ItemL( aContent ) );
+
+    const TDesC8& type( ContentType( item ) );
+
+    TInt retval( KErrNotSupported );
+    
+    if( type == KContentTypeBitmap )
+        {
+        // Unpack icon from pointer
+        CGulIcon* icon( LeaveIfNull( UnpackPtr<CGulIcon>( aBuf ), KErrArgument ) );
+
+        const TDesC& nodeId( iNodeIdGenerator->ContentNodeIdL( aPlugin, item ) );
+        
+        // Publish icon
+        retval = PublishIconL( aPlugin, nodeId, icon, aIndex );
+        }
+    else if ( type == KContentTypeImageSvg )
+        {
+        // Get node id
+        const TDesC& nodeId( iNodeIdGenerator->ContentNodeIdL( aPlugin, item ) );
+        
+        // Publish SVG data
+        retval = PublishDataL( aPlugin, nodeId, aBuf, KContentTypeImageSvg, aIndex );
+        }
+
+    return retval;
+    }
+
+TInt CContentRenderer::DoPublishL( MAiPropertyExtension& aPlugin,
+                                   TInt aContent,
+                                   RFile& aFile,
+                                   TInt aIndex)
+    {
+    //Resolve content item
+    MAiContentItemIterator& iter( 
+            ContentItemIteratorL( aPlugin, EAiPublisherContent ) );
+    
+    const TAiContentItem& item( iter.ItemL( aContent ) );
+
+    const TDesC8& type( ContentType( item ) );
+
+    // Image support
+    if ( type.Find( KContentTypeImage ) != KErrNotFound )
+        {
+        // Find ui element
+        const TDesC& nodeId( iNodeIdGenerator->ContentNodeIdL( aPlugin, item ) );
+
+        CXnNodeAppIf* property( FindNodeByClassL( nodeId, aIndex, 
+                                aPlugin.PublisherInfoL()->iNamespace ) );
+        
+        if( !property )
+            {
+            return KErrNotFound;
+            }
+        
+        // Check priority
+        TInt priority( GetContentPriority( *property ) );
+        
+        CXnNodeAppIf* target( property->ParentL() );
+        
+        if( !target )
+            {
+            return KErrNotSupported;
+            }
+
+        if ( AllowPublishByPriority( *target, priority ) )
+            {
+            // Check if target is newsticker
+            if ( IsParentNewsticker( *target ) )
+                {
+                // Register callback interface
+                CXnNodeAppIf *parent( target->ParentL() );
+                
+                if( !parent )
+                    {
+                    return KErrNotFound;
+                    }
+                                
+                RegisterNewstickerCallbackInterfaceL( *parent );
+                
+                const TAiPublisherInfo* info( aPlugin.PublisherInfoL() );
+                
+                if( info )
+                    {
+                    iNTPublisher.Set( info->iName );
+                    iNTClass = AiUtility::CopyToBufferL( iNTClass, nodeId );
+                    }
+                }
+            
+            // Create transaction element for file
+            MTransactionElement* element =
+                iFactory->CreateImageTransactionElementL( *target,
+                                                          aFile,
+                                                          priority );
+            
+            iPolicyEvaluator->EvaluateContentPolicyL( *target,
+                                                      element->PolicyArray() );
+            iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+                                                         element->PolicyArray() );
+            
+            ProcessTransactionElementL( element );
+            }
+        else
+            {
+            return KErrAccessDenied;
+            }
+        }
+    else 
+        {
+        return KErrNotSupported;        
+        }
+    
+    return KErrNone;
+    }
+
+TInt CContentRenderer::DoCleanL( MAiPropertyExtension& aPlugin,
+                                 TInt aContent,
+                                 TInt aIndex )
+    {
+    // Resolve content item
+    MAiContentItemIterator& iter( 
+            ContentItemIteratorL( aPlugin, EAiPublisherContent ) );
+    
+    const TAiContentItem& item( iter.ItemL( aContent ) );
+
+    const TDesC& nodeId( iNodeIdGenerator->ContentNodeIdL( aPlugin, item ) );
+
+    CXnNodeAppIf* property( FindNodeByClassL( nodeId, aIndex, 
+                            aPlugin.PublisherInfoL()->iNamespace ) );
+
+    if( !property )
+        {
+        return KErrNotFound;
+        }
+    
+    TInt priority( GetContentPriority( *property ) );
+
+    // Navigate to parent
+    CXnNodeAppIf* target( property->ParentL() );
+
+    if( !target )
+        {
+        return KErrNotSupported;
+        }
+    
+    if ( !AllowPublishByPriority( *target, priority ) )
+        {
+        return KErrAccessDenied;
+        }
+
+    if ( IsParentNewsticker( *target ) )
+        {
+        CXnNodeAppIf *parent( target->ParentL() );
+        
+        if( !parent )
+            {
+            return KErrNotFound;
+            }
+               
+        RegisterNewstickerCallbackInterfaceL( *parent );
+        
+        const TAiPublisherInfo* info( aPlugin.PublisherInfoL() );
+        
+        if( info )
+            {
+            iNTPublisher.Set( info->iName );
+            iNTClass = AiUtility::CopyToBufferL( iNTClass, nodeId );
+            }
+        }
+    if( target->Type()->Type() ==
+        XnListQueryDialogInterface::MXnListQueryDialogInterface::Type())
+        {
+        // Get the data interface for dialog and delete data
+        XnListQueryDialogInterface::MXnListQueryDialogInterface* listQuery( NULL );
+        XnComponentInterface::MakeInterfaceL( listQuery, *target );
+        LeaveIfNull( listQuery, KErrNotSupported );
+        listQuery->DeleteItem( aIndex -1 );// plugins publish ordinals not indexes
+        return KErrNone;
+        }
+    
+    // Create transaction element for empty content
+    MTransactionElement* element =
+        iFactory->CreateEmptyContentTransactionElementL( *target, aIndex );
+
+    iPolicyEvaluator->EvaluateEmptyContentPolicyL( *target,
+                                                   element->PolicyArray() );
+    iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+                                                   element->PolicyArray() );
+
+    ProcessTransactionElementL( element );
+      
+    if ( priority > KErrNotFound ) // Only for prioritized elements
+        {
+        // Add current ui element into content refresh map
+        HBufC* uiElementId = PropertyValueL( *target,
+                                         XnPropertyNames::common::KId );
+        return RefreshContentL( uiElementId, priority );
+        }
+    
+    return KErrNone;
+    }
+
+void CContentRenderer::SetImmediateMode( TBool aImmediateMode )
+    {
+    iImmediateMode = aImmediateMode;
+    }
+
+TBool CContentRenderer::IsImmediateMode() const
+    {
+    return iImmediateMode;
+    }
+
+void CContentRenderer::ProcessTransactionElementL( MTransactionElement* aElement )
+    {
+    LeaveIfNull( aElement, KErrArgument );
+    
+    if ( IsImmediateMode() || iStack->IsEmpty() )
+        {
+        // No transaction. Commit element immediately
+        TBool layoutChanged = EFalse;
+        
+        RPropertyHashMap propertyHashMap;
+        aElement->CommitL(layoutChanged, propertyHashMap);
+        SetPropertyArraysL( propertyHashMap );
+        propertyHashMap.Close();
+        
+        iFactory->ReleaseTransactionElement( aElement );
+        StartContentRefresh();
+        
+        // Re-layout
+        iAppUi.UiEngineL()->RenderUIL();
+        }
+    else
+        {
+        // Append transaction element to transaction
+        MTransaction* tr = iStack->Top();
+        tr->Append( *aElement );
+        }
+    }
+
+CXnNodeAppIf* CContentRenderer::FindNodeByClassL( const TDesC& aCid,
+                                                  TInt aIndex,
+                                                  const TDesC8& aNs )
+    {
+    // Find node
+    HBufC8* classId = CnvUtfConverter::ConvertFromUnicodeToUtf8L(aCid);
+    CleanupStack::PushL(classId);
+    
+    RPointerArray<CXnNodeAppIf> nodes = iAppUi.UiEngineL()->FindNodeByClassL( *classId, aNs );
+
+    CleanupStack::PopAndDestroy(classId);
+
+    CleanupClosePushL( nodes );
+
+    for ( TInt i = 0; i < nodes.Count(); ++i )
+        {
+        CXnNodeAppIf* node = nodes[i];
+
+        const TDesC8* name =
+            PropertyValue( *node, AiUiDef::xml::property::KName );
+
+        if ( name && ( *name == AiUiDef::xml::name::KOrdinal ) )
+            {
+            const TDesC8* value =
+                PropertyValue( *node, AiUiDef::xml::property::KValue );
+
+            if ( value )
+                {
+                // Try to parse index from string either
+
+                TInt32 index( 0 );
+                User::LeaveIfError( AiUtility::ParseInt( index, *value ) );
+
+                if ( index == aIndex )
+                    {
+                    CleanupStack::PopAndDestroy(&nodes);
+                    return node;
+                    }
+                }
+            }
+        else if ( name && ( *name == AiUiDef::xml::name::KTarget ) )
+            {            
+            const TDesC8* target =
+                           PropertyValue( *node, AiUiDef::xml::property::KValue );
+            
+            CXnNodeAppIf* targetNode = FindNodeByIdL( *target, node->Namespace() );
+            if ( targetNode )
+                {
+                CleanupStack::PopAndDestroy( &nodes );
+                return targetNode;
+                }
+            }
+        else if ( nodes.Count() == 1 ) // Only one node in class
+            {
+            // No ordinal specified
+			node = nodes[ 0 ];
+			CleanupStack::PopAndDestroy(&nodes);
+            return node;
+            }
+        }
+    
+    CleanupStack::PopAndDestroy( &nodes );
+    
+    return NULL; // Never reached. Needed to omit compiler warning
+    }
+
+CXnNodeAppIf* CContentRenderer::FindNodeByIdL( const TDesC& aCid, const TDesC& aNs )
+    {
+    // Find node
+    return LeaveIfNull( iAppUi.UiEngineL()->FindNodeByIdL( aCid, aNs ),
+                        KErrNotFound );
+    }
+
+CXnNodeAppIf* CContentRenderer::FindNodeByIdL( const TDesC8& aCid, const TDesC8& aNs )
+    {
+    // Find node
+    return LeaveIfNull( iAppUi.UiEngineL()->FindNodeByIdL( aCid, aNs ),
+                        KErrNotFound );
+    }
+
+TInt CContentRenderer::PublishIconL( MAiPropertyExtension& aPlugin,
+                                     const TDesC& aCid,
+                                     CGulIcon* aIcon,
+                                     TInt aIndex,
+                                     CXnNodeAppIf* aResource )
+    {
+    // Find proiperty element by class
+    CXnNodeAppIf* property( FindNodeByClassL( aCid, aIndex, 
+                            aPlugin.PublisherInfoL()->iNamespace ) );
+    
+    if( !property )
+        {
+        return KErrNotFound;
+        }
+    
+    // Get priority information
+    TInt priority( GetContentPriority( *property ) );
+    
+    // Navigate to parent
+    CXnNodeAppIf* target( property->ParentL() );
+    
+    if( !target )
+        {
+        return KErrNotFound;
+        }
+
+    // Check priority
+    if ( !AllowPublishByPriority( *target, priority ) )
+        {
+        return KErrAccessDenied;        
+        }
+    
+    // Special handling of newsticker
+    if ( IsParentNewsticker( *target ) )
+        {
+        // Register callback interface
+        CXnNodeAppIf *parent( target->ParentL() );
+        
+        if( !parent )
+            {
+            return KErrNotFound;
+            }
+                
+        RegisterNewstickerCallbackInterfaceL( *parent );
+        
+        const TAiPublisherInfo* info( aPlugin.PublisherInfoL() );
+        
+        if( info )
+            {
+            iNTPublisher.Set( info->iName );
+            iNTClass = AiUtility::CopyToBufferL( iNTClass, aCid );
+            }
+        }
+
+    MTransactionElement* element =
+        iFactory->CreateImageTransactionElementL( *target,
+                                                  aIcon,
+                                                  priority );
+
+    if ( aResource )
+        {
+        iPolicyEvaluator->EvaluateResourcePolicyL( *target,
+                                                   *aResource,
+                                                   element->PolicyArray() );
+        iPolicyEvaluator->EvaluateContentPolicyL( *target,
+                                                  element->PolicyArray() );
+        iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+                                                     element->PolicyArray() );
+        }
+
+    else
+        {
+        iPolicyEvaluator->EvaluateContentPolicyL( *target,
+                                                  element->PolicyArray() );
+        iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+                                                     element->PolicyArray() );
+        }
+
+    ProcessTransactionElementL( element );
+    
+    return KErrNone;
+    }
+
+TInt CContentRenderer::PublishDataL( MAiPropertyExtension& aPlugin,
+                                     const TDesC& aCid,
+                                     const TDesC8& aData,
+                                     const TDesC8& aContentType,
+                                     TInt aIndex,
+                                     CXnNodeAppIf* aResource )
+    {
+    CXnNodeAppIf* property( FindNodeByClassL( aCid, aIndex, 
+                            aPlugin.PublisherInfoL()->iNamespace ) );
+
+    if( !property )
+        {
+        return KErrNotFound;
+        }
+    
+    TInt priority( GetContentPriority( *property ) );
+    
+    // Navigate to parent
+    CXnNodeAppIf* target( property->ParentL() );
+    
+    if( !target )
+        {
+        return KErrNotFound;
+        }
+
+    if ( !AllowPublishByPriority( *target, priority ) )
+        {
+        return KErrAccessDenied;        
+        }
+
+    if ( !CDataBufferTransactionElement::IsSupported( *target, aContentType ) )
+        {
+        return KErrNotSupported;        
+        }
+        
+    // Handle newsticker 
+    if ( IsParentNewsticker( *target ) )
+        {
+        CXnNodeAppIf *parent( target->ParentL() );
+        
+        if( !parent )
+            {
+            return KErrNotFound;
+            }
+                
+        RegisterNewstickerCallbackInterfaceL( *parent );
+        
+        const TAiPublisherInfo* info( aPlugin.PublisherInfoL() );
+        
+        if( info )
+            {
+            iNTPublisher.Set( info->iName );
+            iNTClass = AiUtility::CopyToBufferL( iNTClass, aCid );
+            }
+        }
+        
+    MTransactionElement* element =
+        iFactory->CreateDataBufferTransactionElementL( *target,
+                                                       aData,
+                                                       priority );
+    
+    if ( aResource )
+        {
+        iPolicyEvaluator->EvaluateResourcePolicyL( *target,
+                                                   *aResource,
+                                                   element->PolicyArray() );
+        iPolicyEvaluator->EvaluateContentPolicyL( *target,
+                                                  element->PolicyArray() );
+        iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+                                                     element->PolicyArray() );
+        }
+    else
+        {
+        iPolicyEvaluator->EvaluateContentPolicyL( *target,
+                                                  element->PolicyArray() );
+        iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+                                                     element->PolicyArray() );
+        }
+
+    ProcessTransactionElementL( element );
+    
+    return KErrNone;
+    }
+
+TBool CContentRenderer::AllowPublishByPriority( CXnNodeAppIf& aUiElement,
+                                                TInt aPriority ) const
+    {
+    // Get ui element id
+    const TDesC8* uiElementId = PropertyValue( aUiElement,
+                                               XnPropertyNames::common::KId );
+                                         
+    if ( uiElementId )
+        {
+        // compare given priority with the current value of ui element
+        return iContentPriorityMap->OverrideContent( *uiElementId, aPriority );
+        }
+    
+    return EFalse; // priority cannot be used, because ui element does not have id
+    }
+
+void CContentRenderer::StartContentRefresh()
+    {
+    // Cancel ongoing refresh
+    iTimer->Cancel();
+    
+    if ( iRefreshableUiElements.Count() > 0 )
+        {
+        // Refreshable elements exist. Start timer to make refresh asynchronous 
+        iTimer->Start( TTimeIntervalMicroSeconds32( 0 ),
+                       TTimeIntervalMicroSeconds32( 0 ),
+                       TCallBack( RefreshContentCallback, this ) );
+        }
+    }
+
+/**
+ * Adds ui element to list of refreshable elements
+ *
+ * @param aUiElementId ui element id
+ * @param aOldPriority old priority value
+ */                         
+TInt CContentRenderer::RefreshContentL( HBufC* aUiElementId,
+                                        TInt aOldPriority )
+    {
+    if( !aUiElementId )
+        {
+        return KErrArgument;
+        }
+        
+    // Take ownership of aUiElementId
+    CleanupStack::PushL( aUiElementId );
+    
+    if ( !iFwEventHandler )
+        {
+        // Content refresh event cannot be sent
+        CleanupStack::PopAndDestroy( aUiElementId );
+        return KErrNotReady;
+        }
+    
+    // Find current mapping
+    TInt* oldPriority = iRefreshableUiElements.Find( *aUiElementId );
+    
+    if ( oldPriority )
+        {
+        // Update mapping
+        *oldPriority = aOldPriority;
+        CleanupStack::PopAndDestroy( aUiElementId );
+        }
+    else
+        {
+        // Create new mapping
+        oldPriority = new( ELeave ) TInt( aOldPriority );
+        CleanupStack::PushL( oldPriority );
+    
+        User::LeaveIfError( iRefreshableUiElements.Insert( aUiElementId,
+                                                           oldPriority ) );
+                                                       
+        CleanupStack::Pop( 2, aUiElementId );
+        }
+    
+    return KErrNone;
+    }
+
+/**
+ * Callback function to make content refreshing asynchronous
+ */    
+TInt CContentRenderer::RefreshContentCallback( TAny* aContentRenderer )
+    {
+    if ( !aContentRenderer )
+        {
+        return KErrArgument;
+        }
+        
+    CContentRenderer* renderer = static_cast< CContentRenderer* >( aContentRenderer );
+    TRAP_IGNORE( renderer->SendRefreshContentEventL() );
+    return KErrNone;
+    }
+
+/**
+ * Sends Refresh content event to framework.
+ * Event is sent for content selectors with lower priority than the
+ * last content which has been cleaned from ui element.
+ */ 
+void CContentRenderer::SendRefreshContentEventL()
+    {
+    // Cancel periodic timer.
+    iTimer->Cancel();
+    
+    // Get ui element id and old content priority
+    TPtrHashMapIter< TDesC, TInt> iter( iRefreshableUiElements );
+    iter.Reset();
+    
+    const TDesC* uiElementId = iter.NextKey(); // Never NULL
+    TInt priority = *( iter.CurrentValue() );
+    
+    //  Cleanup item for iterator 
+    TMapCleanupItem cleanup( iter );
+    CleanupReleasePushL( cleanup );
+    
+    // Lookup ui element
+    CXnNodeAppIf* uiElement = FindNodeByIdL( *uiElementId );
+    
+    // Remove current ui element from the map
+    CleanupStack::PopAndDestroy( &cleanup );
+    
+    // Find lower priority content elements associated to this ui element
+    RPointerArray< CXnNodeAppIf > children = uiElement->ChildrenL();
+    
+    // Remove higher priority content elements
+    RemoveNonPriorityElements( children, priority );
+        
+    // Sort array to descending order
+    children.Sort( TLinearOrder< CXnNodeAppIf >( DescendingPriorityOrder ) );
+    
+    // Send event for content selectors in descending priority order.
+    // Continue until first content gets published or array exhausts.
+    for ( TInt i = 0; i < children.Count(); ++i )
+        {
+        CXnNodeAppIf* current = children[ i ];
+        
+        // Get content selector
+        const HBufC* contentSelector = PropertyValueL( *current,
+                                                       XnPropertyNames::common::KClass );
+        
+        if ( contentSelector && iFwEventHandler->RefreshContent( *contentSelector ))
+            {
+            break;
+            }
+        }
+    
+    // Free content selector array
+    children.Reset();
+    
+    // Continue content refresh for next ui element.
+    StartContentRefresh();    
+    }
+
+void CContentRenderer::TitleScrolled( TInt aTitleIndex )
+    {
+    if ( iCallbackHandler )
+        {
+        TRAP_IGNORE( iCallbackHandler->TitleScrolledL( iNTPublisher,
+                                                       *iNTClass,
+                                                       aTitleIndex ) );
+        }
+    }
+    
+void CContentRenderer::TitleToScroll( TInt aTitleIndex )
+    {
+    if ( iCallbackHandler )
+        {
+        TRAP_IGNORE( iCallbackHandler->TitleToScrollL( iNTPublisher,
+                                                       *iNTClass,
+                                                       aTitleIndex ) );        
+        }
+    }
+
+TBool CContentRenderer::IsParentNewsticker( CXnNodeAppIf& aTarget )
+    {
+    CXnNodeAppIf* parent = NULL;
+    TRAP_IGNORE( parent = aTarget.ParentL() );
+    if ( !parent )
+        {
+        return EFalse;
+        }
+    CXnType* typeInfo = parent->Type();
+    
+    if ( !typeInfo )
+        {
+        return EFalse;
+        }
+        
+    return ( typeInfo->Type() == XnNewstickerInterface::MXnNewstickerInterface::Type());
+    }
+    
+void CContentRenderer::RegisterNewstickerCallbackInterfaceL( CXnNodeAppIf& aTarget )
+    {
+    if ( !iCallbackHandler )
+        {
+        // Instantiate callback handler
+        CNewstickerCallbackHandler* handler = CNewstickerCallbackHandler::NewLC( *iFwEventHandler );
+
+        // Set callback handler
+        iCallbackHandler = handler;
+        CleanupStack::Pop( handler );
+        }
+        // Obtain newsticker component interface
+        XnNewstickerInterface::MXnNewstickerInterface* newsticker = NULL;
+        XnComponentInterface::MakeInterfaceL( newsticker, aTarget );
+        
+        LeaveIfNull( newsticker, KErrGeneral );
+        
+        // Set callback interface
+        newsticker->SetCallbackInterfaceL( this );
+    }
+
+void CContentRenderer::CleanPluginFromUiL( MAiPropertyExtension& aPlugin )
+    {
+    TInt itemCount = 0;
+    
+    // Resolve content items
+    MAiContentItemIterator& iter = ContentItemIteratorL( aPlugin, EAiPublisherContent );
+    iter.Reset();
+    
+    // Clean all content items
+    while ( iter.HasNext() )
+        {
+        const TAiContentItem& item = iter.NextL();
+
+        const TDesC& nodeId = iNodeIdGenerator->ContentNodeIdL( aPlugin, item );
+        
+        // Find nodes
+        HBufC8* nodeId8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L(nodeId);
+        CleanupStack::PushL(nodeId8);
+
+        RPointerArray<CXnNodeAppIf> nodes = iAppUi.UiEngineL()->FindNodeByClassL( 
+            *nodeId8, aPlugin.PublisherInfoL()->iNamespace );
+
+        CleanupStack::PopAndDestroy(nodeId8);
+
+        itemCount += nodes.Count(); 
+        
+        CleanupClosePushL( nodes );
+
+        for ( TInt i = 0; i < nodes.Count(); ++i )
+            {
+            CXnNodeAppIf* property = nodes[i];
+            
+            TInt priority = GetContentPriority( *property );
+
+            // Navigate to parent
+            CXnNodeAppIf* target = LeaveIfNull( property->ParentL(), KErrNotFound );
+
+            if ( AllowPublishByPriority( *target, priority ) )
+                {
+                // Create transaction element for empty content
+                MTransactionElement* element =
+                    iFactory->CreateEmptyContentTransactionElementL( *target, 0 );
+
+                iPolicyEvaluator->EvaluateEmptyContentPolicyL( *target,
+                                                               element->PolicyArray() );
+                iPolicyEvaluator->EvaluateVisibilityPolicyL( *target,
+                                                               element->PolicyArray() );
+                                                      
+                ProcessTransactionElementL( element );
+                  
+                if ( priority > KErrNotFound ) // Only for prioritized elements
+                    {
+                    // Add current ui element into content refresh map
+                    HBufC* uiElementId = PropertyValueL( *target,
+                                                         XnPropertyNames::common::KId );
+                    RefreshContentL( uiElementId, priority );
+                    }
+                }
+            }
+            
+        CleanupStack::PopAndDestroy(&nodes);
+        }
+        
+    if ( itemCount == 0 )
+        {
+        //Nothing to clean from UI. Cancel transaction outside current trap harness
+        User::Leave( KErrNotFound );
+        }
+    }
+
+//  End of File