emailuis/emailui/src/FreestyleEmailUiHtmlViewerContainer.cpp
branchRCL_3
changeset 64 3533d4323edc
child 70 968773a0b6ef
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailuis/emailui/src/FreestyleEmailUiHtmlViewerContainer.cpp	Wed Sep 01 12:28:57 2010 +0100
@@ -0,0 +1,2299 @@
+/*
+* Copyright (c) 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:  CFsEmailUiHtmlViewerContainer class implementation
+*
+*/
+
+
+#include "emailtrace.h"
+#include <AknsDrawUtils.h>
+#include <coemain.h>
+#include <commdbconnpref.h>
+#include <bautils.h>
+#include <biditext.h>
+#include <StringLoader.h>
+#include <e32base.h>
+#include <badesca.h>
+#include <utf.h>
+#include <finditemengine.h>
+
+//<cmail>
+#include "cfsmailmessage.h"
+//</cmail>
+#include <brctlinterface.h>
+#include <sysutil.h>
+#include <schemehandler.h>
+
+#include <FreestyleEmailUi.rsg>
+
+#include "FreestyleEmailUiAppui.h"
+#include "FreestyleEmailUiUtilities.h"
+#include "FreestyleEmailUiHtmlViewerContainer.h"
+#include "FreestyleEmailUiHtmlViewerView.h"
+#include "FreestyleEmailUiShortcutBinding.h"
+
+#include "FreestyleMessageHeaderHTML.h"
+#include "FreestyleMessageHeaderURLEventHandler.h"
+#include "FreestyleEmailUiAttachmentsListModel.h"
+
+_LIT( KContentIdPrefix, "cid:" );
+_LIT( KCDrive, "c:" );
+_LIT( KHtmlPath, "HtmlFile\\" );
+_LIT( KTempHtmlPath, "temp\\" );
+_LIT( KAllFiles, "*" );
+
+_LIT( KHeaderHtmlFile, "header.html" );
+_LIT( KBodyHtmlFile, "body.html" );
+_LIT( KMessageHtmlFile, "email.html" );
+_LIT( KMessageHtmlRTLFile, "email_rtl.html" );
+_LIT( KZDrive, "z:" );
+_LIT( KHtmlFlagFile, "html.flag" );
+_LIT( KURLSlash, "/");
+// Constants used in html content modification
+const TInt KMaxCharsToSearch( 200 );
+_LIT8( KStartTag, "<html" );
+_LIT8( KHeadTag, "<head>");
+_LIT8( KHtmlHeader1, "<html><head><title></title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=");
+_LIT8( KHtmlHeader2, "\"/></head><body bgcolor=\"#ECECEC\">\xD\xA");
+_LIT8( KHtmlHeader3, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%S\">\n");
+_LIT8( KHtmlEndTags, "\xD\xA</body></html>\xD\xA");
+_LIT8( KCharsetTag8, "charset");
+_LIT( KCharsetTag, "charset");
+_LIT8( KHTMLEmptyContent, "<html><body></body></html>");
+_LIT( KHTMLDataScheme, "data:0");
+
+
+_LIT( KHtmlLineBreak, "<br>" );
+_LIT( KHtmlLineBreakCRLF, "<br>\xD\xA" );
+_LIT( KHtmlLessThan, "&lt;" );
+_LIT( KHtmlGreaterThan, "&gt;" );
+_LIT( KHtmlAmpersand, "&amp;" );
+_LIT( KHtmlQuotation, "&quot;" );
+_LIT( KURLTypeBody, "body");
+
+_LIT( KURLDisplayImages, "cmail://displayImages/" );
+_LIT( KURLLoadImages, "cmail://loadImages/" );
+_LIT( KURLCollapseHeader, "cmail://collapseHeader/" );
+_LIT( KURLExpandHeader, "cmail://expandHeader/" );
+_LIT( KURLExpandItem, "cmail://expand_" );
+_LIT( KURLItemTo, "to" );
+_LIT( KURLItemCc, "cc" );
+_LIT( KURLItemBcc, "bcc" );
+_LIT( KURLItemAttachments, "attachments" );
+
+const TText KGreaterThan = 0x3e;
+const TText KLessThan = 0x3c;
+const TText KAmpersand = 0x26;
+const TText KQuotation = 0x22;
+const TText KSOH = 0x01; // Start Of Heading
+const TText KLF = 0x0a; // Line Feed
+const TText KUnicodeNewLineCharacter = 0x2028;
+const TText KUnicodeParagraphCharacter = 0x2029;
+const TReal KOverlayButtonMarginX = 0.01; // 1%
+const TReal KOverlayButtonMarginY = 0.01; // 1%
+const TReal KOverlayButtonSizeP = 0.15; // 15%
+const TReal KOverlayButtonSizeLs = 0.20; // 25%
+
+
+const TInt KStatusIndicatorHeight = 55;
+const TInt KStatusIndicatorXMargin = 58;
+const TInt KStatusIndicatorBottomMargin = 6;
+
+// CONSTANTS
+// Zoom levels available on the UI
+const TInt KZoomLevels[] = { 75, 100, 125, 150 };
+const TInt KZoomLevelCount = sizeof( KZoomLevels ) / sizeof( TInt );
+const TInt KZoomLevelIndex100 = 1; // 100 in array KZoomLevels
+
+// CEUiHtmlViewerSettingsKeyListener
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CEUiHtmlViewerSettingsKeyListener::CEUiHtmlViewerSettingsKeyListener( MObserver& aObserver, TUint32 aKey )
+    : CActive( EPriorityStandard ), iObserver( aObserver ), iKey( aKey )
+    {
+    CActiveScheduler::Add(this);
+    StartListening();
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CEUiHtmlViewerSettingsKeyListener::~CEUiHtmlViewerSettingsKeyListener()
+    {
+    Cancel();
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CEUiHtmlViewerSettingsKeyListener::StartListening()
+    {
+    SetActive();
+    iObserver.Repository().NotifyRequest(iKey, iStatus);
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CEUiHtmlViewerSettingsKeyListener::RunL()
+    {
+    iObserver.KeyValueChangedL(iKey);
+    StartListening();
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CEUiHtmlViewerSettingsKeyListener::DoCancel()
+    {
+    iObserver.Repository().NotifyCancel(iKey);
+    }
+
+// CEUiHtmlViewerSettings
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CEUiHtmlViewerSettings* CEUiHtmlViewerSettings::NewL( MObserver& aObserver )
+    {
+    CEUiHtmlViewerSettings* self = new (ELeave) CEUiHtmlViewerSettings(aObserver);
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CEUiHtmlViewerSettings::~CEUiHtmlViewerSettings()
+    {
+    iKeyListeners.ResetAndDestroy();
+    delete iRepository;
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CEUiHtmlViewerSettings::CEUiHtmlViewerSettings( MObserver& aObserver ) : iObserver( aObserver )
+    {
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CEUiHtmlViewerSettings::ConstructL()
+    {
+    iRepository = CRepository::NewL(KFreestyleEmailCenRep);
+    AddKeyListenerL(KFreestyleEmailDownloadHTMLImages);
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CEUiHtmlViewerSettings::AddKeyListenerL( TUint32 aKey )
+    {
+    CEUiHtmlViewerSettingsKeyListener* listener = 
+        new (ELeave) CEUiHtmlViewerSettingsKeyListener( *this, aKey );
+    CleanupStack::PushL( listener );
+    iKeyListeners.AppendL( listener );
+    CleanupStack::Pop( listener );
+    UpdateValue( aKey );
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CEUiHtmlViewerSettings::UpdateValue( TUint32 aKey )
+    {
+    TInt value;
+    iRepository->Get(aKey, value);
+    switch (aKey)
+        {
+        case KFreestyleEmailDownloadHTMLImages:
+            // 0 = automatic, 1 = ask always
+            iFlags.Assign(aKey, value == 0);
+            break;
+        default:
+            iFlags.Assign(aKey, value);
+            break;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CEUiHtmlViewerSettings::KeyValueChangedL( TUint32 aKey )
+    {
+    UpdateValue(aKey);
+    iObserver.ViewerSettingsChangedL(aKey);
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CRepository& CEUiHtmlViewerSettings::Repository()
+    {
+    return *iRepository;
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool CEUiHtmlViewerSettings::AutoLoadImages() const
+    {
+    return iFlags.IsSet(EAutoLoadImages);
+    }
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CFsEmailUiHtmlViewerContainer* CFsEmailUiHtmlViewerContainer::NewL(
+    CFreestyleEmailUiAppUi& aAppUi, CFsEmailUiHtmlViewerView& aView )
+    {
+    FUNC_LOG;
+    CFsEmailUiHtmlViewerContainer* self =
+        new (ELeave) CFsEmailUiHtmlViewerContainer( aAppUi, aView );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// C++ constructor.
+// ---------------------------------------------------------------------------
+//
+CFsEmailUiHtmlViewerContainer::CFsEmailUiHtmlViewerContainer(
+    CFreestyleEmailUiAppUi& aAppUi, CFsEmailUiHtmlViewerView& aView )
+    :
+    iAppUi( aAppUi ),
+    iView( aView ),
+    iFs( iCoeEnv->FsSession() ),
+    iFirstTime( ETrue ),
+    iZoomLevel( KZoomLevelIndex100 )
+    {
+    FUNC_LOG;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CFsEmailUiHtmlViewerContainer::~CFsEmailUiHtmlViewerContainer()
+    {
+    FUNC_LOG;
+    delete iViewerSettings;
+    if ( iObservingDownload && iAppUi.DownloadInfoMediator() )
+        {
+        iAppUi.DownloadInfoMediator()->StopObserving( this );
+        }
+    iFile.Close();
+    iLinkContents.Close();
+    iMessageParts.Close();
+    delete iEventHandler;
+    delete iBrCtlInterface;
+    iConnection.Close();
+    iSocketServer.Close();
+    delete iStatusIndicator;
+    delete iOverlayControlNext;
+    delete iOverlayControlPrev;
+    }
+
+void CFsEmailUiHtmlViewerContainer::PrepareForExit()
+    {
+    FUNC_LOG;
+    HideDownloadStatus();
+    if ( iObservingDownload && iAppUi.DownloadInfoMediator() )
+        {
+        iAppUi.DownloadInfoMediator()->StopObserving( this );
+        iObservingDownload = EFalse;
+        }
+    delete iBrCtlInterface;
+    iBrCtlInterface = NULL;
+    iConnection.Close();
+    iSocketServer.Close();
+    }
+
+void CFsEmailUiHtmlViewerContainer::PrepareForMessageNavigation()
+    {
+    FUNC_LOG;
+    ResetContent();
+    }
+
+void CFsEmailUiHtmlViewerContainer::ZoomInL()
+    {
+    SetZoomLevelL( ZoomLevelL() + 1 );
+    }
+
+void CFsEmailUiHtmlViewerContainer::ZoomOutL()
+    {
+    SetZoomLevelL( ZoomLevelL() - 1 );
+    }
+
+TInt CFsEmailUiHtmlViewerContainer::ZoomLevelL() const
+    {
+    FUNC_LOG;
+    TInt zoomLevelIdx = iBrCtlInterface->BrowserSettingL(
+            TBrCtlDefs::ESettingsCurrentZoomLevelIndex );
+
+    // Behaviour of zooming in Browser Control Interface is different in version 7.1
+    // than in previous versions and we need to support both. In older versions there
+    // are 4 preset zoom levels while version 7.1 can zoom to any percent.
+    RArray<TUint>* zoomLevels = iBrCtlInterface->ZoomLevels();
+
+    if ( !zoomLevels || !zoomLevels->Count() || ( *zoomLevels )[0] != KZoomLevels[0] )
+        {
+        // new browser:
+        // BrowserControlIf gives zoom level percentage insted of index to array
+        TBool found = EFalse;
+
+        for ( TInt i = 0 ; i < KZoomLevelCount && !found ; ++i )
+            {
+            if ( zoomLevelIdx == KZoomLevels[i] )
+                {
+                zoomLevelIdx = i;
+                found = ETrue;
+                }
+            }
+
+        if ( !found )
+            {
+            zoomLevelIdx = KErrNotFound;
+            }
+        }
+    return zoomLevelIdx;
+    }
+
+void CFsEmailUiHtmlViewerContainer::SetZoomLevelL( const TInt aZoomLevel )
+    {
+    FUNC_LOG;
+    TInt newValue = KMinTInt;
+
+    // Behaviour of zooming in Browser Control Interface is different in version 7.1
+    // than in previous versions and we need to support both. In older versions there
+    // are 4 preset zoom levels while version 7.1 can zoom to any percent.
+    RArray<TUint>* zoomLevels = iBrCtlInterface->ZoomLevels();
+
+    if ( !zoomLevels || !zoomLevels->Count() || ( *zoomLevels )[0] != KZoomLevels[0] )
+        {
+        // new browser:
+        // BrowserControlIf takes zoom level percentage insted of index to array
+        if ( aZoomLevel >= 0 && aZoomLevel < KZoomLevelCount )
+            {
+            newValue = KZoomLevels[aZoomLevel];
+            }
+        }
+    else
+        {
+        // old browser
+        newValue = aZoomLevel;
+        }
+
+    iZoomLevel = ( newValue > KMinTInt ) ? newValue : aZoomLevel;
+    iBrCtlInterface->SetBrowserSettingL(
+        TBrCtlDefs::ESettingsCurrentZoomLevelIndex, iZoomLevel );
+    }
+
+TInt CFsEmailUiHtmlViewerContainer::DoZoom( TAny* aPtr  )
+    {
+    TRAPD( error, reinterpret_cast<CFsEmailUiHtmlViewerContainer*>( aPtr )->DoZoomL() );
+    return error;
+    }
+
+void CFsEmailUiHtmlViewerContainer::DoZoomL()
+    {
+    iBrCtlInterface->SetBrowserSettingL(
+        TBrCtlDefs::ESettingsCurrentZoomLevelIndex, iZoomLevel );
+    }
+
+TInt CFsEmailUiHtmlViewerContainer::MaxZoomLevel() const
+    {
+    return KZoomLevelCount;
+    }
+
+
+void CFsEmailUiHtmlViewerContainer::CreateBrowserControlInterfaceL()
+    {
+    FUNC_LOG;
+
+    if ( iBrCtlInterface )
+        {
+       	SetZoomLevelL(100);
+		iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsAutoLoadImages, iViewerSettings->AutoLoadImages() );
+       	return;
+        }
+
+    TUint brCtlCapabilities = TBrCtlDefs::ECapabilityClientResolveEmbeddedURL |
+                              TBrCtlDefs::ECapabilityDisplayScrollBar |
+                              TBrCtlDefs::ECapabilityClientNotifyURL |
+                              TBrCtlDefs::ECapabilityLoadHttpFw |
+                              TBrCtlDefs::ECapabilityCursorNavigation |
+                              TBrCtlDefs::ECapabilityPinchZoom |
+                              TBrCtlDefs::ECapabilityFitToScreen;
+
+    // Set browsercontrol to whole screen
+    TRect rect( TPoint(), Size() );
+
+    iBrCtlInterface = CreateBrowserControlL(
+            this, // aParent
+            rect,  // aRect
+            brCtlCapabilities, // aBrCtlCapabilities
+            TBrCtlDefs::ECommandIdBase, // aCommandIdBase
+            NULL, // aBrCtlSoftkeysObserver
+            this, // aBrCtlLinkResolver
+            this, // aBrCtlSpecialLoadObserver
+            NULL, // aBrCtlLayoutObserver
+            NULL, // aBrCtlDialogsProvider
+            this, // aBrCtlWindowObserver
+            NULL // aBrCtlDownloadObserver
+            );
+
+    iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsEmbedded, ETrue );
+    iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsAutoLoadImages, iViewerSettings->AutoLoadImages() );
+    iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsPageOverview, EFalse );
+    iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsTextWrapEnabled, ETrue );
+    iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsFontSize, TBrCtlDefs::EFontSizeLevelLarger );
+    }
+
+void CFsEmailUiHtmlViewerContainer::ConstructL()
+    {
+    FUNC_LOG;
+    iViewerSettings = CEUiHtmlViewerSettings::NewL(*this);
+
+    SetHtmlFolderPathL();
+    BaflUtils::EnsurePathExistsL( iFs, iHtmlFolderPath );
+    SetTempHtmlFolderPath();
+    BaflUtils::EnsurePathExistsL( iFs, iTempHtmlFolderPath );
+    SetHTMLResourceFlagFullName();
+    EnsureHTMLResourceL();
+
+    CreateWindowL();
+    
+#if defined( BRDO_MULTITOUCH_ENABLED_FF ) && !defined ( __WINSCW__ )   
+    //Enable advance pointer info for multi-touch.
+    Window().EnableAdvancedPointers();
+#endif 
+
+    
+    iEventHandler = CFreestyleMessageHeaderURLEventHandler::NewL( iAppUi, iView );
+
+    TRect nextButtonRect = OverlayButtonRect( EFalse );
+    iOverlayControlNext = COverlayControl::NewL( this, this, nextButtonRect,
+            EMbmFreestyleemailuiQgn_indi_cmail_arrow_next,
+            EMbmFreestyleemailuiQgn_indi_cmail_arrow_next_mask );
+
+    TRect prevButtonRect = OverlayButtonRect( ETrue );
+    iOverlayControlPrev = COverlayControl::NewL( this, this, prevButtonRect,
+            EMbmFreestyleemailuiQgn_indi_cmail_arrow_previous,
+            EMbmFreestyleemailuiQgn_indi_cmail_arrow_previous_mask );
+    iScrollPosition = 0;
+    iAttachmentDownloadImageHandle = 0;
+
+    iTouchFeedBack = MTouchFeedback::Instance();
+    iTouchFeedBack->EnableFeedbackForControl(this, ETrue);
+
+    CreateBrowserControlInterfaceL();
+    SetRect( iView.ContainerRect() );
+
+    ActivateL();
+    }
+
+void CFsEmailUiHtmlViewerContainer::MakeVisible( TBool aVisible )
+    {
+    UpdateOverlayButtons( aVisible );
+    CCoeControl::MakeVisible( aVisible );
+    }
+
+void CFsEmailUiHtmlViewerContainer::HandleOverlayPointerEventL( COverlayControl* aControl,
+        const TPointerEvent& aEvent )
+    {
+    if( aEvent.iType == TPointerEvent::EButton1Up )
+        {
+        if( aControl == iOverlayControlNext )
+            {
+            iView.HandleCommandL( EFsEmailUiCmdNextMessage );
+            }
+        else if( aControl == iOverlayControlPrev )
+            {
+            iView.HandleCommandL( EFsEmailUiCmdPreviousMessage );
+            }
+        }
+    }
+
+void CFsEmailUiHtmlViewerContainer::UpdateOverlayButtons( TBool aVisible )
+    {
+    TBool nextAvailable = EFalse;
+    TBool prevAvailable = EFalse;
+    if( iMessage )
+        {
+        TFSMailMsgId currentMsgId = iMessage->GetMessageId();
+        TFSMailMsgId tmpMsgId;
+        TFSMailMsgId tmpMsgFolderId;
+        nextAvailable = iAppUi.IsNextMsgAvailable( currentMsgId, tmpMsgId, tmpMsgFolderId );
+        prevAvailable = iAppUi.IsPreviousMsgAvailable( currentMsgId, tmpMsgId, tmpMsgFolderId );
+        }
+
+    if( iOverlayControlPrev )
+        {
+        iOverlayControlPrev->SetRect( OverlayButtonRect( ETrue ) );
+        iOverlayControlPrev->MakeVisible( aVisible && prevAvailable );
+        }
+    if( iOverlayControlNext )
+        {
+        iOverlayControlNext->SetRect( OverlayButtonRect( EFalse ) );
+        iOverlayControlNext->MakeVisible( aVisible && nextAvailable );
+        }
+    }
+
+// Get rect for button
+TRect CFsEmailUiHtmlViewerContainer::OverlayButtonRect( TBool aLeft )
+    {
+    TRect rect = Rect();
+    TSize size = rect.Size();
+
+    TBool landscape = size.iWidth > size.iHeight;
+    TInt buttonSize;
+
+    if( landscape )
+        {
+        buttonSize = size.iHeight * KOverlayButtonSizeLs;
+        }
+    else
+        {
+        buttonSize = size.iWidth * KOverlayButtonSizeP;
+        }
+
+    rect.iBr.iY = size.iHeight * (1-KOverlayButtonMarginY);
+
+    if( aLeft )
+        {
+        rect.iTl.iX = size.iWidth * KOverlayButtonMarginX;
+        rect.iBr.iX = rect.iTl.iX + buttonSize;
+        }
+    else
+        {
+        rect.iBr.iX = size.iWidth * (1 - KOverlayButtonMarginX);
+        rect.iTl.iX = rect.iBr.iX - buttonSize;
+        }
+
+    rect.iTl.iY = rect.iBr.iY - buttonSize;
+    return rect;
+    }
+
+// Getter for br contro, interface
+CBrCtlInterface* CFsEmailUiHtmlViewerContainer::BrowserControlIf()
+    {
+    FUNC_LOG;
+    return iBrCtlInterface;
+    }
+
+void CFsEmailUiHtmlViewerContainer::LoadContentFromFileL( const TDesC& aFileName )
+    {
+    FUNC_LOG;
+    iBrCtlInterface->LoadFileL( aFileName );
+    }
+
+void CFsEmailUiHtmlViewerContainer::LoadContentFromFileL( RFile& aFile )
+    {
+    FUNC_LOG;
+    iBrCtlInterface->LoadFileL( aFile );
+    }
+
+void CFsEmailUiHtmlViewerContainer::LoadContentFromUrlL( const TDesC& aUrl )
+    {
+    FUNC_LOG;
+    iBrCtlInterface->LoadUrlL( aUrl );
+    }
+
+// ---------------------------------------------------------------------------
+// Loads content from given mail message.
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::LoadContentFromMailMessageL(
+        CFSMailMessage* aMailMessage, TBool aResetScrollPos )
+    {
+    FUNC_LOG;
+    ASSERT( aMailMessage );
+    iMessage = aMailMessage;
+    // Cancel any browser fetch operation, just in case the browser is still
+    // loading a previous message (since we are about to overwrite it).
+    CancelFetch();
+
+    TPath headerHtmlFile;
+    headerHtmlFile.Copy( iHtmlFolderPath );
+    headerHtmlFile.Append( KHeaderHtmlFile );
+
+    // insert email header into email.html file
+    // CFreestyleMessageHeaderHTML will replace contents of email.html
+    // So, no need to clear the contents
+    if(aResetScrollPos)
+        {
+        iScrollPosition = 0;
+        }
+    const TInt visibleWidth(iAppUi.ClientRect().Width());
+    CFreestyleMessageHeaderHTML::ExportL( *iMessage, iFs, headerHtmlFile, visibleWidth, iScrollPosition,
+            iViewerSettings->AutoLoadImages() || iAppUi.DisplayImagesCache().Contains(*iMessage), iFlags );
+    
+    // Remove all previously created files from temporary HTML folder
+    EmptyTempHtmlFolderL();
+
+    TRAPD( error, PrepareBodyHtmlL( KBodyHtmlFile ) );
+    if ( error != KErrNone )
+        {
+        WriteEmptyBodyHtmlL( KBodyHtmlFile );
+        }
+
+    // pass the emailHtmlFile to the browser for it to load
+    TPath emailHtmlFile;
+    emailHtmlFile.Copy( iHtmlFolderPath );
+    if ( !AknLayoutUtils::LayoutMirrored() )
+        {
+        emailHtmlFile.Append( KMessageHtmlFile );
+        }
+    else
+        {
+        emailHtmlFile.Append( KMessageHtmlRTLFile );
+        }
+
+    // If scroll position is not to be reset, re-creation of browser control
+    // interface object is skipped (we're just reloading the page with new
+    // content)
+    if ( aResetScrollPos )
+        {
+        CreateBrowserControlInterfaceL();
+        }
+    
+    LoadContentFromFileL( emailHtmlFile );
+
+    UpdateOverlayButtons( ETrue );
+    }
+
+// ---------------------------------------------------------------------------
+// Reset content
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::ResetContent( TBool aDisconnect,
+    TBool aClearFlags )
+    {
+    FUNC_LOG;
+    if ( iBrCtlInterface )
+        {
+        TRAP_IGNORE(
+                iBrCtlInterface->HandleCommandL( ( TInt )TBrCtlDefs::ECommandIdBase +
+                        ( TInt )TBrCtlDefs::ECommandFreeMemory ) );
+        if (aDisconnect)
+            {
+            TRAP_IGNORE(
+                    iBrCtlInterface->HandleCommandL( ( TInt )TBrCtlDefs::ECommandIdBase +
+                                                      ( TInt )TBrCtlDefs::ECommandDisconnect ) );
+            }
+        }
+    iFile.Close();
+    iLinkContents.Reset();
+    iMessageParts.Reset();
+    iMessage = NULL;
+    if ( aClearFlags )
+        {
+        iFlags.ClearAll();
+        }
+    iScrollPosition = 0;
+    }
+
+// ---------------------------------------------------------------------------
+// From CCoeControl.
+// ---------------------------------------------------------------------------
+//
+CCoeControl* CFsEmailUiHtmlViewerContainer::ComponentControl( TInt aIndex ) const
+    {
+    FUNC_LOG;
+    switch ( aIndex )
+        {
+        case 0:
+            {
+            return iBrCtlInterface;
+            }
+        case 1:
+            {
+            return iOverlayControlNext;
+            }
+        case 2:
+            {
+            return iOverlayControlPrev;
+            }
+        case 3:
+            {
+            if ( iStatusIndicator )
+                return iStatusIndicator;
+            else
+                return NULL;
+            }
+        default:
+            {
+            return NULL;
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From CCoeControl.
+// ---------------------------------------------------------------------------
+//
+TInt CFsEmailUiHtmlViewerContainer::CountComponentControls() const
+    {
+    FUNC_LOG;
+    if ( iStatusIndicator )
+        {
+        return 4;
+        }
+    else
+        {
+        return 3;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From CCoeControl.
+// Draw this application's view to the screen
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::Draw( const TRect& /*aRect*/ ) const
+    {
+    FUNC_LOG;
+    // Get the standard graphics context
+    CWindowGc& gc = SystemGc();
+
+    // Gets the control's extent
+    TRect rect = Rect();
+
+    // Clears the screen
+    gc.Clear( rect );
+    }
+
+// ---------------------------------------------------------------------------
+// From CCoeControl.
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::SizeChanged()
+    {
+    FUNC_LOG;
+
+    TRect rect = Rect();
+    if ( iBrCtlInterface )
+        {
+        iBrCtlInterface->SetRect( rect );
+        }
+
+    UpdateOverlayButtons( IsVisible() );
+
+    if ( iStatusIndicator )
+        {
+        TRect rect = CalcAttachmentStatusRect();
+        iStatusIndicator->SetRect( rect );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From CCoeControl.
+// ---------------------------------------------------------------------------
+//
+TKeyResponse CFsEmailUiHtmlViewerContainer::OfferKeyEventL(
+    const TKeyEvent& aKeyEvent, TEventCode aType )
+    {
+    FUNC_LOG;
+
+    TKeyResponse retVal = EKeyWasNotConsumed;
+
+    // Handle keyboard shortcuts already on key down event as all keys
+    // do not necessarily send the key event at all.
+    if ( aType == EEventKeyDown )
+        {
+        // Check keyboard shortcuts
+        TInt shortcutCommand = iAppUi.ShortcutBinding().CommandForShortcutKey(
+            aKeyEvent, CFSEmailUiShortcutBinding::EContextHtmlViewer );
+
+        if ( shortcutCommand != KErrNotFound )
+            {
+            iView.HandleCommandL( shortcutCommand );
+            retVal = EKeyWasConsumed;
+            }
+        }
+
+    if ( iBrCtlInterface && retVal == EKeyWasNotConsumed )
+        {
+        TKeyEvent event = aKeyEvent;
+        if ( iBrCtlInterface->FocusedElementType() == TBrCtlDefs::EElementButton
+             && ( aKeyEvent.iScanCode == EStdKeyNkpEnter 
+                  || aKeyEvent.iScanCode == EStdKeyEnter ) )
+            {
+            // Enter key events are converted to selection key event in
+            // order to get browser to handle them in similar way.
+            event.iScanCode = EStdKeyDevice3;
+            event.iCode = aKeyEvent.iCode ? EKeyDevice3 : 0;
+            }
+        retVal = iBrCtlInterface->OfferKeyEventL( event, aType );
+        }
+
+    iView.SetMskL();
+
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// From MBrCtlSpecialLoadObserver.
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::NetworkConnectionNeededL(
+        TInt* aConnectionPtr,
+        TInt* aSockSvrHandle,
+        TBool* aNewConn,
+        TApBearerType* aBearerType )
+    {
+    FUNC_LOG;
+    *aBearerType = EApBearerTypeAllBearers;
+
+    if ( iFirstTime )
+        {
+        User::LeaveIfError( iSocketServer.Connect( KESockDefaultMessageSlots ) );
+        User::LeaveIfError( iConnection.Open( iSocketServer, KConnectionTypeDefault ) );
+        TCommDbConnPref prefs;
+        prefs.SetDialogPreference( ECommDbDialogPrefDoNotPrompt );
+        prefs.SetDirection( ECommDbConnectionDirectionOutgoing );
+        prefs.SetIapId( 0 ); // Ask for access point
+        User::LeaveIfError( iConnection.Start( prefs ) );
+        *aNewConn = ETrue;
+        iFirstTime = EFalse;
+        }
+    else
+        {
+        *aNewConn = EFalse;
+        }
+
+    *aConnectionPtr = reinterpret_cast<TInt>(&iConnection);
+    *aSockSvrHandle = iSocketServer.Handle();
+    }
+
+// ---------------------------------------------------------------------------
+// From MBrCtlSpecialLoadObserver.
+// ---------------------------------------------------------------------------
+//
+TBool CFsEmailUiHtmlViewerContainer::HandleRequestL(
+    RArray<TUint>* /*aTypeArray*/, CDesCArrayFlat* /*aDesArray*/ )
+    {
+    FUNC_LOG;
+    // Let browser control handle these
+    return EFalse;
+    }
+
+// ---------------------------------------------------------------------------
+// From MBrCtlSpecialLoadObserver.
+// ---------------------------------------------------------------------------
+//
+TBool CFsEmailUiHtmlViewerContainer::HandleDownloadL(
+    RArray<TUint>* /*aTypeArray*/, CDesCArrayFlat* /*aDesArray*/ )
+    {
+    FUNC_LOG;
+    // Let browser control handle these
+    return EFalse;
+    }
+
+// ---------------------------------------------------------------------------
+// From MFSEmailDownloadInformationObserver.
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::RequestResponseL( const TFSProgress& aEvent,
+    const TPartData& aPart )
+    {
+    FUNC_LOG;
+    if ( aEvent.iProgressStatus == TFSProgress::EFSStatus_RequestComplete )
+        {
+        MBrCtlLinkContent* linkContent = NULL;
+        for ( TInt ii = iMessageParts.Count() - 1; ii >= 0 && !linkContent; --ii )
+            {
+            if ( iMessageParts[ii] == aPart )
+                {
+                iMessageParts.Remove( ii );
+                linkContent = iLinkContents[ii];
+                iLinkContents.Remove( ii );
+                }
+            }
+
+        if ( !iMessageParts.Count() && iAppUi.DownloadInfoMediator() )
+            {
+            iAppUi.DownloadInfoMediator()->StopObserving( this );
+            }
+
+        if ( iMessage && linkContent )
+            {
+            CFSMailMessagePart* part = iMessage->ChildPartL( aPart.iMessagePartId );
+            CleanupStack::PushL( part );
+            RFile contentFile = part->GetContentFileL();
+            CleanupClosePushL( contentFile );
+            HBufC8* content = ReadContentFromFileLC( contentFile, *part );
+            linkContent->HandleResolveComplete(
+                part->GetContentType(), KNullDesC(), content );
+            CleanupStack::PopAndDestroy( content );
+            CleanupStack::PopAndDestroy( &contentFile );
+            CleanupStack::PopAndDestroy( part );
+            }
+
+        if ( iMessage )
+            {
+            LoadContentFromMailMessageL( iMessage, EFalse );
+            UpdateOverlayButtons( ETrue );
+            }
+        }
+    else if ( aEvent.iProgressStatus == TFSProgress::EFSStatus_RequestCancelled ||
+            aEvent.iProgressStatus < 0 )
+        {
+        if ( iAppUi.DownloadInfoMediator() )
+            {
+            iAppUi.DownloadInfoMediator()->StopObserving( this, aPart.iMessageId );
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From MBrCtlLinkResolver.
+// ---------------------------------------------------------------------------
+//
+TBool CFsEmailUiHtmlViewerContainer::ResolveEmbeddedLinkL(
+    const TDesC& aEmbeddedUrl, const TDesC& /*aCurrentUrl*/,
+    TBrCtlLoadContentType /*aLoadContentType*/,
+    MBrCtlLinkContent& aEmbeddedLinkContent )
+    {
+    FUNC_LOG;
+    TBool linkResolved = EFalse;
+
+    // Check if given link contains content ID
+    if ( aEmbeddedUrl.Left( KContentIdPrefix().Length() ).CompareF( KContentIdPrefix ) == 0 )
+        {
+        TPtrC cid = aEmbeddedUrl.Mid( KContentIdPrefix().Length() );
+        linkResolved = ResolveLinkL( cid, ETrue, aEmbeddedLinkContent );
+        }
+    else
+        {
+        // Replace all slash character with backslash characters
+        HBufC* embeddedUrl = aEmbeddedUrl.AllocLC();
+        TPtr ptr = embeddedUrl->Des();
+        _LIT( KBackslash, "\\" );
+        for ( TInt pos = ptr.Locate('/'); pos >= 0; pos = ptr.Locate('/') )
+            {
+            ptr.Replace( pos, 1, KBackslash );
+            }
+
+        // Check whether given url refers to file in the temporary html folder
+        TInt pos = embeddedUrl->FindF( iTempHtmlFolderPath );
+        if ( pos >= 0 )
+            {
+            TPtrC filename = embeddedUrl->Mid( pos + iTempHtmlFolderPath.Length() );
+            linkResolved = ResolveLinkL( filename, EFalse, aEmbeddedLinkContent );
+            }
+
+        CleanupStack::PopAndDestroy( embeddedUrl );
+        }
+
+    // Return whether link is resolved by host application.
+    return linkResolved;
+    }
+
+// ---------------------------------------------------------------------------
+// From MBrCtlLinkResolver.
+// ---------------------------------------------------------------------------
+//
+TBool CFsEmailUiHtmlViewerContainer::ResolveLinkL( const TDesC& aUrl,
+    const TDesC& /*aCurrentUrl*/, MBrCtlLinkContent& /*aBrCtlLinkContent*/ )
+    {
+    FUNC_LOG;
+    if ( IsMessageBodyURLL(aUrl) )
+        {
+        if ( iMessage )
+            {
+            iView.StartFetchingMessageL();
+            }
+        return ETrue;
+        }
+    else
+        {
+        if ( NeedToLaunchBrowserL( aUrl ) )
+            {
+            LaunchBrowserL( aUrl );
+            return ETrue;
+            }
+        else
+            {
+            return iEventHandler->HandleEventL( aUrl );
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From MBrCtlLinkResolver.
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::CancelAll()
+    {
+    FUNC_LOG;
+    }
+
+// ---------------------------------------------------------------------------
+// From MBrCtlSoftkeysObserver
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::UpdateSoftkeyL(
+    TBrCtlKeySoftkey /*aKeySoftkey*/, const TDesC& /*aLabel*/,
+    TUint32 /*aCommandId*/,
+    TBrCtlSoftkeyChangeReason /*aBrCtlSoftkeyChangeReason*/ )
+    {
+    FUNC_LOG;
+    }
+
+// ---------------------------------------------------------------------------
+// Set HTML folder path name
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::SetHtmlFolderPathL()
+    {
+    FUNC_LOG;
+    iHtmlFolderPath.Copy( KCDrive );
+
+    TFileName privatePath;
+    User::LeaveIfError( iFs.PrivatePath( privatePath ) );
+    iHtmlFolderPath.Append( privatePath );
+
+    iHtmlFolderPath.Append( KHtmlPath );
+    }
+
+// ---------------------------------------------------------------------------
+// Sets temporary HTML folder path name
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::SetTempHtmlFolderPath()
+    {
+    FUNC_LOG;
+    iTempHtmlFolderPath.Copy( iHtmlFolderPath );
+    iTempHtmlFolderPath.Append( KTempHtmlPath );
+    }
+
+// ---------------------------------------------------------------------------
+// Remove all previously created files from temporary HTML folder
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::EmptyTempHtmlFolderL()
+    {
+    FUNC_LOG;
+    // Delete all files from temp folder
+    TFileName allFiles;
+    allFiles.Append( iTempHtmlFolderPath );
+    allFiles.Append( KAllFiles );
+    TInt err = BaflUtils::DeleteFile( iFs, allFiles );
+    if ( err != KErrNotFound && err != KErrNone )
+        {
+        User::LeaveIfError( err );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Copies given read-only file to HTML file
+// ---------------------------------------------------------------------------
+//
+// <cmail>
+void CFsEmailUiHtmlViewerContainer::CopyToHtmlFileL( CFSMailMessagePart& aHtmlBodyPart, const TDesC& aFileName )
+    {
+    FUNC_LOG;
+    TFileName targetFileName;
+    targetFileName.Copy( iTempHtmlFolderPath );
+    targetFileName.Append( aFileName );
+
+    RFile htmlFile = aHtmlBodyPart.GetContentFileL();
+    CleanupClosePushL( htmlFile );
+
+    // Read content from given source file
+    HBufC8* content = ReadContentFromFileLC( htmlFile, aHtmlBodyPart );
+
+    // Write content to target file
+    WriteContentToFileL( *content, targetFileName, aHtmlBodyPart );
+
+    CleanupStack::PopAndDestroy( content );
+    CleanupStack::PopAndDestroy( &htmlFile );
+    }
+// </cmail>
+
+// ---------------------------------------------------------------------------
+// Copies given buffer to HTML file
+// ---------------------------------------------------------------------------
+//
+// <cmail>
+void CFsEmailUiHtmlViewerContainer::ConvertToHtmlFileL( CFSMailMessagePart& aTextBodyPart, const TDesC& aHtmlFileName )
+    {
+    FUNC_LOG;
+    TFileName targetFileName;
+    targetFileName.Copy( iTempHtmlFolderPath );
+    targetFileName.Append( aHtmlFileName );
+
+    TInt contentsize = aTextBodyPart.FetchedContentSize();
+      
+    TInt limit(0);
+    TInt err = iViewerSettings->Repository().Get( KFreestyleMaxBodySize , limit );
+    limit *= KKilo; // cenrep value is in kB, 0 means unlimited
+
+    if ( limit == 0 || err )
+        {
+        limit = KMaxTInt;
+        }
+    
+    TInt size = Min(limit,contentsize);
+    HBufC* content = HBufC::NewLC( size );
+    TPtr contentPtr( content->Des() );
+
+    aTextBodyPart.GetContentToBufferL( contentPtr, 0 );
+    //When we found EFSMsgFlag_BodyTruncated was set, add "--Message too long--" in the end of plain html view
+    if ( limit < contentsize )
+        {
+        // Disable this is PS1 until we have translations available             
+//		 HBufC* addingText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_VIEW_ADDITIONAL_INFO , limit/KKilo );
+//		 TInt pos = contentPtr.Length() - addingText->Length();
+//		 contentPtr.Replace(pos,addingText->Length(),*addingText);
+//         CleanupStack::PopAndDestroy( addingText );
+         aTextBodyPart.SetFlag(EFSMsgFlag_BodyTruncated);
+        }
+    
+    ConvertToHTML( *content, targetFileName, aTextBodyPart );
+    CleanupStack::PopAndDestroy( content );
+    }
+
+// ---------------------------------------------------------------------------
+// Reads given file content to buffer and return pointer to it
+// ---------------------------------------------------------------------------
+//
+HBufC8* CFsEmailUiHtmlViewerContainer::ReadContentFromFileLC( RFile& aFile, 
+   CFSMailMessagePart& aBodyPart )
+    {
+    FUNC_LOG;
+    TInt fileSize = 0;
+    User::LeaveIfError( aFile.Size( fileSize ) );
+ 
+    HBufC* contentType = aBodyPart.GetContentType().AllocLC();
+    TInt length = contentType->Locate(';');
+    if( length >= 0 )
+        {
+        contentType->Des().SetLength( length );
+        }
+    TBool body = KFSMailContentTypeTextPlain().CompareF( contentType->Des() ) == 0 ||
+                 KFSMailContentTypeTextHtml().CompareF( contentType->Des() ) == 0; 
+    CleanupStack::PopAndDestroy( contentType );
+    
+    if ( body )
+        {
+        // limit message size if not done already by plugins
+        TInt limit(0);
+        TInt err = iViewerSettings->Repository().Get( KFreestyleMaxBodySize , limit );
+        limit *= KKilo; // cenrep value is in kB, 0 means unlimited
+ 
+        if ( limit == 0 || err )
+           {
+           limit = KMaxTInt;
+           }
+        fileSize = Min( limit, fileSize ); // read no more than limit bytes..
+     
+        TInt contentSize = aBodyPart.ContentSize();
+        TInt fetchedSize = aBodyPart.FetchedContentSize();
+        
+        if ( ( limit!=KMaxTInt && fileSize < contentSize ) 
+          || ( fetchedSize < contentSize ) ) 
+            {
+            aBodyPart.SetFlag( EFSMsgFlag_BodyTruncated );
+            }
+        }
+    HBufC8* buffer = HBufC8::NewLC( fileSize );
+    TPtr8 ptr = buffer->Des();
+    User::LeaveIfError( aFile.Read( ptr, fileSize ) );
+    return buffer;
+    }
+
+// ---------------------------------------------------------------------------
+// Writes buffer content to given file
+// ---------------------------------------------------------------------------
+//
+// <cmail>
+void CFsEmailUiHtmlViewerContainer::WriteContentToFileL( const TDesC8& aContent,
+    const TDesC& aFileName, CFSMailMessagePart& aHtmlBodyPart )
+    {
+    FUNC_LOG;
+
+    RBuf8 buffer;
+    buffer.CreateL( aContent );
+    buffer.CleanupClosePushL();
+
+    if ( SysUtil::DiskSpaceBelowCriticalLevelL( &iFs, buffer.Size(), EDriveC ) )
+         {
+         // Can not write the data, there's not enough free space on disk.
+         User::Leave( KErrDiskFull );
+        }
+    else
+        {
+        RFile targetFile;
+        CleanupClosePushL( targetFile );
+
+        User::LeaveIfError( targetFile.Replace( iFs, aFileName, EFileWrite ) );
+
+        // Try to find initial html tag (both '<html' and '<HTML' versions are searched)
+        TInt startTagOffset = buffer.Left( KMaxCharsToSearch ).FindF( KStartTag );
+
+        // Modifying text/html atta IF there's no '<html>' tag anywhere in
+        // the begining of file (KMaxCharsToSearch) AND there is charset
+        // parameter available
+        TBool modificationNeeded( EFalse );
+        if( startTagOffset == KErrNotFound )
+            {
+            modificationNeeded = ETrue;
+            }
+
+        // Write starting metadata if needed
+        if ( modificationNeeded )
+            {
+            HBufC8* charSet = GetCharacterSetL( aHtmlBodyPart );
+            CleanupStack::PushL( charSet );
+
+            User::LeaveIfError( targetFile.Write( KHtmlHeader1 ) );
+            User::LeaveIfError( targetFile.Write( *charSet ) );
+            User::LeaveIfError( targetFile.Write( KHtmlHeader2 ) );
+            CleanupStack::PopAndDestroy( charSet );
+            }
+        else
+            {
+            // Charset tag not found in html body
+
+            if ( buffer.Left( KMaxCharsToSearch ).FindF( KCharsetTag8 ) == KErrNotFound )
+                {
+                TInt startPos(0);
+                if ( ( startPos = buffer.Left( KMaxCharsToSearch ).FindF( KHeadTag ) ) != KErrNotFound )
+                    {
+
+                    HBufC8* charSet = GetCharacterSetL( aHtmlBodyPart );
+                    CleanupStack::PushL( charSet );
+
+                    HBufC8* metaBuffer = HBufC8::NewLC( charSet->Des().Length() + KHtmlHeader3().Length() );
+                    TPtr8 metaHeader( metaBuffer->Des() );
+                    metaHeader.AppendFormat( KHtmlHeader3, charSet );
+                    TInt maxLength = buffer.Length() + metaHeader.Length();
+                    buffer.ReAllocL( maxLength );
+
+                    startPos += KHeadTag().Length();
+                    buffer.Insert( startPos, metaHeader );
+
+                    CleanupStack::PopAndDestroy( metaBuffer );
+                    CleanupStack::PopAndDestroy( charSet );
+                    }
+                }
+            }
+
+        // Write the original content
+        User::LeaveIfError( targetFile.Write( buffer ) );
+        if( aHtmlBodyPart.GetFlags() & EFSMsgFlag_BodyTruncated )
+        	{
+            //When we found EFSMsgFlag_BodyTruncated was set, add "--- Message limited to %N kB ---" in the end of html view
+             TInt limit(0);
+             TInt err = iViewerSettings->Repository().Get( KFreestyleMaxBodySize , limit );
+             limit *= KKilo; // cenrep value is in kB, 0 means unlimited
+             if ( limit == 0 || err )
+                 {
+                 limit = KMaxTInt;
+                 }
+
+// Disable this is PS1 until we have translations available             
+//          HBufC* addingText = StringLoader::LoadLC( R_FREESTYLE_EMAIL_UI_VIEW_ADDITIONAL_INFO, limit/KKilo );
+//			HBufC8* addingText8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L( *addingText );       
+//			CleanupStack::PopAndDestroy( addingText );
+//			CleanupStack::PushL( addingText8 );
+//			User::LeaveIfError( targetFile.Write( *addingText8 ) );
+//			CleanupStack::PopAndDestroy( addingText8 );
+        	}
+        // Write ending metadata if needed
+        if ( modificationNeeded || (aHtmlBodyPart.GetFlags()&EFSMsgFlag_BodyTruncated) )
+            {
+            INFO("Add end tags");
+            User::LeaveIfError( targetFile.Write( KHtmlEndTags ) );
+            }
+
+        CleanupStack::PopAndDestroy( &targetFile );
+        }
+    CleanupStack::PopAndDestroy( &buffer );
+// </cmail>
+    }
+
+// ---------------------------------------------------------------------------
+// Finds the attachment from the list that matches the given content ID
+// ---------------------------------------------------------------------------
+//
+CFSMailMessagePart* CFsEmailUiHtmlViewerContainer::MatchingAttacmentL(
+    const TDesC& aContentId,
+    const RPointerArray<CFSMailMessagePart>& aAttachments ) const
+    {
+    FUNC_LOG;
+    TBool contentFound = EFalse;
+    CFSMailMessagePart* attachment = NULL;
+    TInt attachmentCount = aAttachments.Count();
+
+    // Check whether one of the attachments has the given conten ID
+    for ( TInt i = 0; i < attachmentCount && !contentFound; i++ )
+        {
+        attachment = aAttachments[i];
+        const TDesC& contentId = attachment->ContentID();
+        if ( contentId.Compare( aContentId ) == 0 )
+            {
+            contentFound = ETrue;
+            }
+        }
+
+    // If attacment with given content ID was not found, check whether
+    // the given content ID contains the name of one of the attachments
+    for ( TInt i = 0; i < attachmentCount && !contentFound; ++i )
+        {
+        attachment = aAttachments[i];
+        const TDesC& name = attachment->AttachmentNameL();
+        if ( aContentId.FindF( name ) >= 0 )
+            {
+            contentFound = ETrue;
+            }
+        }
+
+    if ( !contentFound )
+        {
+        attachment = NULL;
+        }
+    return attachment;
+    }
+
+// ---------------------------------------------------------------------------
+// Resolves link referring to file in temporary HTML folder
+// ---------------------------------------------------------------------------
+//
+TBool CFsEmailUiHtmlViewerContainer::ResolveLinkL( const TDesC& aLink,
+    TBool aContentId, MBrCtlLinkContent& aEmbeddedLinkContent  )
+    {
+    FUNC_LOG;
+    TBool linkResolved = EFalse;
+    CFSMailMessagePart* attachment = NULL;
+
+    RPointerArray<CFSMailMessagePart> attachments;
+    CleanupResetAndDestroyClosePushL( attachments );
+    iMessage->AttachmentListL( attachments );
+
+    if ( aContentId )
+        {
+        attachment = MatchingAttacmentL( aLink, attachments );
+        }
+    else
+        {
+        const TInt attachmentCount = attachments.Count();
+        for ( TInt ii = 0; ii < attachmentCount && !attachment; ++ii )
+            {
+            if ( aLink.CompareF( attachments[ii]->AttachmentNameL() ) == 0 )
+                {
+                attachment = attachments[ii];
+                }
+            }
+        }
+
+    if ( attachment )
+        {
+        DownloadAttachmentL( *attachment, aEmbeddedLinkContent );
+        linkResolved = ETrue;
+        }
+
+    CleanupStack::PopAndDestroy( &attachments );
+    return linkResolved;
+    }
+
+// ---------------------------------------------------------------------------
+// Download attachment and return the content via MBrCtlLinkContent interface
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::DownloadAttachmentL(
+    CFSMailMessagePart& aAttachment, MBrCtlLinkContent& aEmbeddedLinkContent )
+    {
+    FUNC_LOG;
+    if ( aAttachment.FetchLoadState() == EFSFull )
+        {
+        RFile attachmentFile = aAttachment.GetContentFileL();
+        CleanupClosePushL( attachmentFile );
+        HBufC8* content = ReadContentFromFileLC( attachmentFile, aAttachment );
+        aEmbeddedLinkContent.HandleResolveComplete(
+            aAttachment.GetContentType(), KNullDesC(), content );
+        CleanupStack::PopAndDestroy( content );
+        CleanupStack::PopAndDestroy( &attachmentFile );
+        }
+    else
+        {
+        TPartData partData;
+        if( iMessage )
+            {
+            partData.iMailBoxId = iMessage->GetMailBoxId();
+            partData.iFolderId = iMessage->GetFolderId();
+            partData.iMessageId = iMessage->GetMessageId();
+
+            partData.iMessagePartId = aAttachment.GetPartId();
+
+            if ( iAppUi.DownloadInfoMediator() &&
+                 iAppUi.DownloadInfoMediator()->IsDownloadableL( partData ) )
+                {
+                ASSERT( iLinkContents.Count() == iMessageParts.Count() );
+
+                // Append message part details and embedded link content interface
+                // to corresponding arrays so that the content can be returned
+                // when the download is completed.
+                iLinkContents.AppendL( &aEmbeddedLinkContent );
+                if ( iMessageParts.Append( partData ) != KErrNone )
+                    {
+                    iLinkContents.Remove( iLinkContents.Count() - 1 );
+                    }
+
+                ASSERT( iLinkContents.Count() == iMessageParts.Count() );
+                if(!iView.GetAsyncFetchStatus())
+                    {
+                    iAppUi.DownloadInfoMediator()->AddObserver( this, aAttachment.GetMessageId() );
+                    iObservingDownload=ETrue;
+                    iAppUi.DownloadInfoMediator()->DownloadL( partData, EFalse );
+                    }
+                }
+            }
+        }
+    }
+
+void CFsEmailUiHtmlViewerContainer::SetHTMLResourceFlagFullName()
+    {
+    FUNC_LOG;
+    iHtmlResourceFlagPath.Copy( iHtmlFolderPath );
+    iHtmlResourceFlagPath.Append( KHtmlFlagFile );
+    }
+
+void CFsEmailUiHtmlViewerContainer::EnableHTMLResourceFlagL()
+    {
+    FUNC_LOG;
+    RFile flag;
+    User::LeaveIfError( flag.Replace(iFs, iHtmlResourceFlagPath, EFileWrite) );
+    flag.Close();
+    }
+
+TBool CFsEmailUiHtmlViewerContainer::HTMLResourceFlagEnabled()
+    {
+    FUNC_LOG;
+    return BaflUtils::FileExists( iFs, iHtmlResourceFlagPath );
+    }
+
+void CFsEmailUiHtmlViewerContainer::CopyHTMLResourceL()
+    {
+    FUNC_LOG;
+
+    TPath htmlFolderPathInZ;
+    htmlFolderPathInZ.Copy( KZDrive );
+
+    TFileName privatePath;
+    User::LeaveIfError( iFs.PrivatePath( privatePath ) );
+    htmlFolderPathInZ.Append( privatePath );
+
+    htmlFolderPathInZ.Append( KHtmlPath );
+
+    CDir* dirList;
+    TPath listSpec;
+    listSpec.Copy( htmlFolderPathInZ );
+
+    listSpec.Append( _L("*.*") );
+    User::LeaveIfError( iFs.GetDir( listSpec,  KEntryAttMaskSupported, ESortByName, dirList ) );
+    CleanupStack::PushL( dirList );
+    for ( TInt i=0; i < dirList->Count(); i++)
+        {
+        TPath sourceFileFullName;
+        sourceFileFullName.Copy( htmlFolderPathInZ );
+        sourceFileFullName.Append( (*dirList)[i].iName );
+
+        TBool isFolder( EFalse );
+        BaflUtils::IsFolder( iFs, sourceFileFullName, isFolder);
+        if ( isFolder )
+            {
+            break;
+            }
+
+        TPath targetFileFullName;
+        targetFileFullName.Copy( iHtmlFolderPath );
+        targetFileFullName.Append( (*dirList)[i].iName );
+        BaflUtils::DeleteFile( iFs, targetFileFullName );
+
+        BaflUtils::CopyFile( iFs, sourceFileFullName, targetFileFullName);
+        }
+    CleanupStack::PopAndDestroy( dirList );
+    }
+
+void CFsEmailUiHtmlViewerContainer::EnsureHTMLResourceL()
+    {
+    FUNC_LOG;
+
+    if ( !HTMLResourceFlagEnabled() )
+        {
+        CopyHTMLResourceL();
+        EnableHTMLResourceFlagL();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Writes buffer content to given file after adding tags
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::ConvertToHTML( const TDesC& aContent,
+    const TDesC& aFileName, CFSMailMessagePart& /*aTextBodyPart*/ )
+    {
+    FUNC_LOG;
+   
+    if ( SysUtil::DiskSpaceBelowCriticalLevelL( &iFs, aContent.Size(), EDriveC ) )
+        {
+        // Can not write the data, there's not enough free space on disk.
+        User::Leave( KErrDiskFull );
+        }
+
+    RBuf htmlText;
+    CleanupClosePushL( htmlText );
+        
+    PlainTextToHtmlConverter::PlainTextToHtmlL( aContent, htmlText );
+    WriteToFileL( aFileName, htmlText );
+        
+    CleanupStack::PopAndDestroy( &htmlText );
+    }
+
+
+TInt CFsEmailUiHtmlViewerContainer::TotalLengthOfItems( CFindItemEngine& aItemEngine ) const
+    {
+    TInt totalLength( 0 );
+    CFindItemEngine::SFoundItem item;
+    aItemEngine.ResetPosition();
+    for ( TBool available( aItemEngine.Item( item ) ); available; available = aItemEngine.NextItem( item ) )
+        {
+        totalLength += item.iLength;
+        }
+    aItemEngine.ResetPosition();
+    return totalLength;
+    }
+
+// ---------------------------------------------------------------------------
+// Get Character set from CFSMailMessagePart
+// ---------------------------------------------------------------------------
+//
+// <cmail>
+HBufC8* CFsEmailUiHtmlViewerContainer::GetCharacterSetL( CFSMailMessagePart& aHtmlBodyPart )
+    {
+    FUNC_LOG;
+
+    CDesCArray& contentTypeArray( aHtmlBodyPart.ContentTypeParameters() );
+    HBufC8* charSet = KNullDesC8().AllocLC();
+
+    for ( TInt i = 0; i < contentTypeArray.Count(); i++ )
+        {
+        TPtrC contentEntry( contentTypeArray.MdcaPoint( i ) );
+        if ( ( contentEntry.FindF( KCharsetTag ) != KErrNotFound ) &&
+                contentTypeArray.Count() >= ( i+1) )
+            {
+            TPtrC value( contentTypeArray.MdcaPoint( i+1 ) );
+            if ( value.Length() )
+                {
+                CleanupStack::PopAndDestroy( charSet );
+                charSet = NULL;
+                charSet = HBufC8::NewLC( value.Length() );
+                charSet->Des().Copy( value );
+                break;
+                }
+            }
+        i++;
+        }
+
+    CleanupStack::Pop( charSet );
+    return charSet;
+    }
+
+void CFsEmailUiHtmlViewerContainer::StopObserving()
+    {
+    if( iObservingDownload )
+        {
+        if ( iMessage && iAppUi.DownloadInfoMediator() )
+            {
+            iAppUi.DownloadInfoMediator()->StopObserving( this, iMessage->GetMessageId() );
+            }
+        iObservingDownload=EFalse;
+        }
+    }
+
+void CFsEmailUiHtmlViewerContainer::CancelFetch()
+    {
+    FUNC_LOG;
+    if ( iBrCtlInterface )
+        {
+        TRAP_IGNORE( iBrCtlInterface->HandleCommandL( (TInt)TBrCtlDefs::ECommandCancelFetch + (TInt)TBrCtlDefs::ECommandIdBase ));
+        }
+    }
+
+void CFsEmailUiHtmlViewerContainer::ClearCacheAndLoadEmptyContent()
+    {
+    FUNC_LOG;
+    if ( iBrCtlInterface )
+        {
+        iBrCtlInterface->ClearCache();
+        TUid uid;
+        uid.iUid = KCharacterSetIdentifierUtf8;
+        TRAP_IGNORE( iBrCtlInterface->LoadDataL(KHTMLDataScheme, KHTMLEmptyContent, _L8("text/html"), uid) );
+        }
+    }
+
+void CFsEmailUiHtmlViewerContainer::HandleResourceChange( TInt aType )
+    {
+    CCoeControl::HandleResourceChange( aType );
+    if ( aType == CFsEmailUiViewBase::EScreenLayoutChanged )
+        {
+        RefreshCurrentMailHeader();
+	    SetRect( iView.ContainerRect() );
+        }
+   }
+
+void CFsEmailUiHtmlViewerContainer::RefreshCurrentMailHeader()
+    {
+    if ( iMessage )
+        {
+        // Update the width in header part and reload
+        TPath headerHtmlFile;
+        headerHtmlFile.Copy( iHtmlFolderPath );
+        headerHtmlFile.Append( KHeaderHtmlFile );
+
+            TRAP_IGNORE( CFreestyleMessageHeaderHTML::ExportL( *iMessage, iFs,
+                headerHtmlFile, iAppUi.ClientRect().Width(), iScrollPosition,
+                iViewerSettings->AutoLoadImages() || iAppUi.DisplayImagesCache().Contains(*iMessage),
+                iFlags ) )
+        
+        
+        if(!iEventHandler->IsMenuVisible())
+            {
+            TRAP_IGNORE( ReloadPageL() );
+            }
+        else
+            {
+            //Load page asynchronously after dismissing menu
+            //this is outdated call because it cancels Action menu which is no longer used in 9.2
+           // iEventHandler->DismissMenuAndReload();
+            }
+        }
+    }
+
+void CFsEmailUiHtmlViewerContainer::ReloadPageL()
+    {
+    TRAP_IGNORE( iBrCtlInterface->HandleCommandL( ( TInt )TBrCtlDefs::ECommandIdBase +
+            ( TInt )TBrCtlDefs::ECommandReload ) );
+    }
+
+void CFsEmailUiHtmlViewerContainer::ShowAttachmentDownloadStatusL(
+        TFSProgress::TFSProgressStatus aProgressStatus,
+        const TAttachmentData& aAttachmentData )
+    {
+    TBool freshDraw = EFalse;
+    //If the indicator was displaying fetching body then we will be displaying a different indicator
+    //this is just to make sure the image is updated
+    if(iStatusIndicator)
+        {
+        if (iStatusIndicator->Image())
+            {
+            if(iStatusIndicator->Image()->Handle() != iAttachmentDownloadImageHandle)
+                {
+                freshDraw = ETrue;
+                }
+            }
+        }
+    if ( !iStatusIndicator )
+        {
+        TRect rect = CalcAttachmentStatusRect();
+        iStatusIndicator = CFreestyleEmailUiAknStatusIndicator::NewL( rect, this );
+        freshDraw = ETrue;
+        }
+
+    if ( !iStatusIndicator->IsVisible()
+         || ( aAttachmentData.downloadProgress == KNone )
+         || ( aProgressStatus == TFSProgress::EFSStatus_RequestCancelled ) )
+        {
+        freshDraw = ETrue;
+        }
+
+    TInt duration = KStatusIndicatorDefaultDuration;
+    if ( ( aAttachmentData.downloadProgress == TFSProgress::EFSStatus_RequestComplete )
+         || ( aProgressStatus == TFSProgress::EFSStatus_RequestCancelled )
+         || ( aAttachmentData.downloadProgress == KComplete ) )
+        {
+        duration = KStatusIndicatorAutomaticHidingDuration;
+        }
+
+    HBufC* statusText = NULL;
+    switch ( aProgressStatus )
+        {
+        case TFSProgress::EFSStatus_Status:
+        case TFSProgress::EFSStatus_RequestComplete:
+            {
+            CDesCArray* descArray = new (ELeave) CDesCArrayFlat( 1 );
+            CleanupStack::PushL( descArray );
+            descArray->AppendL( aAttachmentData.fileName );
+            CArrayFix<TInt>* intArray = new (ELeave) CArrayFixFlat<TInt>( 1 );
+            CleanupStack::PushL( intArray );
+            intArray->AppendL( aAttachmentData.downloadProgress );
+
+            statusText = StringLoader::LoadL( R_FSE_VIEWER_ATTACHMENTS_LIST_DOWNLOAD,
+                                              *descArray,
+                                              *intArray );
+            CleanupStack::PopAndDestroy( intArray );
+            CleanupStack::PopAndDestroy( descArray );
+            CleanupStack::PushL( statusText );
+            }
+        break;
+
+        case TFSProgress::EFSStatus_RequestCancelled:
+            {
+            statusText = aAttachmentData.fileName.AllocLC();
+            }
+        break;
+
+        default:
+            statusText = KNullDesC().AllocLC();
+            break;
+        }
+
+    if ( statusText->Length() > 0 )
+        {
+        if ( freshDraw )
+            {
+            CFbsBitmap* image = NULL;
+            CFbsBitmap* imageMask = NULL;
+            if ( aProgressStatus == TFSProgress::EFSStatus_RequestCancelled )
+                {
+                iAppUi.FsTextureManager()->ProvideBitmapL(EAttachmentsCancelDownload, image, imageMask );
+                }
+            else
+                {
+                iAppUi.FsTextureManager()->ProvideBitmapL(EAttachmentsDownload, image, imageMask );
+                }
+            if(image)
+                {
+                iAttachmentDownloadImageHandle = image->Handle();
+                }
+            iStatusIndicator->ShowIndicatorL( image, imageMask, statusText, duration );
+            }
+        else
+            {
+            iStatusIndicator->SetTextL( statusText );
+            if ( duration > -1 )
+                {
+                iStatusIndicator->HideIndicator( duration );
+                }
+            }
+        }
+
+    CleanupStack::Pop( statusText );
+    }
+
+TBool CFsEmailUiHtmlViewerContainer::AttachmentDownloadStatusVisible()
+    {
+    if ( iStatusIndicator )
+        {
+        return iStatusIndicator->IsVisible();
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+void CFsEmailUiHtmlViewerContainer::ViewerSettingsChangedL( const TUint32 aKey )
+    {
+    FUNC_LOG;
+    if (aKey == KFreestyleEmailDownloadHTMLImages)
+        {
+        if (iBrCtlInterface)
+            {
+            iBrCtlInterface->SetBrowserSettingL(
+                TBrCtlDefs::ESettingsAutoLoadImages,
+                    iViewerSettings->AutoLoadImages() );
+            if (iViewerSettings->AutoLoadImages() && iMessage)
+                {
+                LoadContentFromMailMessageL(iMessage, EFalse);
+                }
+            }
+        }
+    }
+
+void CFsEmailUiHtmlViewerContainer::HideDownloadStatus()
+    {
+    if ( iStatusIndicator )
+        {
+        iStatusIndicator->MakeVisible( EFalse );
+        }
+    }
+
+TRect CFsEmailUiHtmlViewerContainer::CalcAttachmentStatusRect()
+    {
+    TRect rect( Rect() );
+    TPoint topLeft = rect.iTl;
+    TPoint bottomRight = rect.iBr;
+    TPoint statusTopLeft( topLeft.iX + KStatusIndicatorXMargin, bottomRight.iY - KStatusIndicatorHeight + 1 );
+    TPoint statusBottomRight( bottomRight.iX - KStatusIndicatorXMargin, bottomRight.iY );
+    rect = TRect(statusTopLeft, statusBottomRight);
+    rect.Move(0, -KStatusIndicatorBottomMargin);
+    return rect;
+    }
+
+void CFsEmailUiHtmlViewerContainer::TouchFeedback()
+    {
+    iTouchFeedBack->InstantFeedback(this, ETouchFeedbackBasic);
+    }
+
+/**
+ * The body fetch link is cmail://body/fetch. Look for the URL separator
+ * and the presence of cmail and body on the url.
+ * @param aUrl
+ * return ETrue for  a valid body URL
+ */
+TBool CFsEmailUiHtmlViewerContainer::IsMessageBodyURLL(const TDesC& aUrl)
+    {
+    TInt index = aUrl.Find(KURLSchemeSeparator);
+    if (index == KErrNotFound)
+        {
+        return EFalse;
+        }
+    else
+        {
+        if (aUrl.Compare(KURLLoadImages()) == 0)
+            {
+            iBrCtlInterface->HandleCommandL(TBrCtlDefs::ECommandLoadImages + TBrCtlDefs::ECommandIdBase);
+            return ETrue;
+            }
+        else if (aUrl.Compare(KURLDisplayImages()) == 0)
+            {
+            DisplayStatusIndicatorL(KStatusIndicatorAutomaticHidingDuration);
+			if( iMessage )
+			{
+            iAppUi.DisplayImagesCache().AddMessageL(*iMessage);
+			}
+            iBrCtlInterface->HandleCommandL(TBrCtlDefs::ECommandLoadImages + TBrCtlDefs::ECommandIdBase);
+            return ETrue;
+            }
+        else if (aUrl.Compare(KURLCollapseHeader()) == 0)
+            {
+            TouchFeedback();
+            iFlags.ClearAll();
+            return ETrue;
+            }
+        else if (aUrl.Compare(KURLExpandHeader()) == 0)
+            {
+            TouchFeedback();
+            iFlags.Set( CFreestyleMessageHeaderHTML::EHeaderExpanded );
+            return ETrue;        
+            }
+        else if ( aUrl.Find( KURLExpandItem() ) == 0 ) {
+            const TPtrC item( aUrl.Mid( KURLExpandItem().Length() ) );
+            if ( item.Find( KURLItemTo() ) == 0 )
+                {
+                iFlags.Assign( CFreestyleMessageHeaderHTML::EToExpanded, ETrue );
+                }
+            else if ( item.Find( KURLItemCc() ) == 0 )
+                {
+                iFlags.Assign( CFreestyleMessageHeaderHTML::ECcExpanded, ETrue );
+                }
+            else if ( item.Find( KURLItemBcc() ) == 0 )
+                {
+                iFlags.Assign( CFreestyleMessageHeaderHTML::EBccExpanded, ETrue );
+                }
+            else if ( item.Find( KURLItemAttachments() ) == 0 )
+                {
+                iFlags.Assign( CFreestyleMessageHeaderHTML::EAttachmentExpanded, ETrue );
+                }            
+            return ETrue;        
+        } else if (aUrl.Left(index).CompareF(KURLSchemeCmail) == 0)
+            {
+            TInt bodyIndex = aUrl.Find(KURLTypeBody);
+            if (bodyIndex == KErrNotFound)
+                {
+                return EFalse;
+                }
+            else
+                {
+                TPtrC16 data= aUrl.Mid(bodyIndex);
+                TInt separator = data.Find(KURLSlash);
+                if(separator == KErrNotFound)
+                    {
+                    return EFalse;
+                    }
+                else
+                    {
+                    TPtrC16 temp = data.Mid(separator+1);
+                    TLex lex(temp);
+                    lex.Val(iScrollPosition);
+                    }
+                return ETrue;
+                }
+
+            }
+        else
+            {
+            return EFalse;
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From MBrCtlWindowObserver
+// ---------------------------------------------------------------------------
+//
+CBrCtlInterface* CFsEmailUiHtmlViewerContainer::OpenWindowL( TDesC& /*aUrl*/, TDesC* /*aTargetName*/,
+                                                             TBool /*aUserInitiated*/, TAny* /*aReserved*/ )
+    {
+    return iBrCtlInterface;
+    }
+
+// ---------------------------------------------------------------------------
+// From MBrCtlWindowObserver
+// ---------------------------------------------------------------------------
+//
+CBrCtlInterface* CFsEmailUiHtmlViewerContainer::FindWindowL( const TDesC& /*aTargetName*/ ) const
+    {
+    return NULL;
+    }
+
+// ---------------------------------------------------------------------------
+// From MBrCtlWindowObserver
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::HandleWindowCommandL( const TDesC& /*aTargetName*/,
+                                                          TBrCtlWindowCommand /*aCommand*/ )
+    {
+
+    }
+
+// ---------------------------------------------------------------------------
+// Check if a tap on the URL requires browser(standalone) to be launched
+// ---------------------------------------------------------------------------
+//
+TBool CFsEmailUiHtmlViewerContainer::NeedToLaunchBrowserL( const TDesC& aUrl )
+    {
+    TBool launchBrowser( ETrue );
+    // look for file:///
+    _LIT( KFileLink, "file:///");
+    _LIT( KUrlLink, "http");
+
+    // This might be linking to header.html or body.html frames
+    // Ignore them.
+    if ( aUrl.Left( KFileLink().Length() ).CompareF( KFileLink ) == 0 )
+        {
+        //Now there is a chance that this could be from HTML folder
+        // Replace all slash character with backslash characters
+        HBufC* embeddedUrl = aUrl.AllocLC();
+        TPtr ptr = embeddedUrl->Des();
+
+        _LIT( KBackslash, "\\" );
+        for ( TInt pos = ptr.Locate('/'); pos >= 0; pos = ptr.Locate('/') )
+            {
+            ptr.Replace( pos, 1, KBackslash );
+            }
+
+        // Check whether given url refers to file in the html folder
+        TInt pos = embeddedUrl->FindF( iHtmlFolderPath );
+        CleanupStack::PopAndDestroy( embeddedUrl );
+        pos >= 0 ? launchBrowser = EFalse : ETrue;
+        }
+    // Ignore links starting with cmail://
+    else if ( aUrl.Left( KURLSchemeCmail().Length() ).CompareF( KURLSchemeCmail ) == 0 )
+        {
+        launchBrowser = EFalse;
+        }
+    //    THAA-82BEAZ - show popup first
+    else if ( aUrl.Left(KUrlLink().Length() ).CompareF( KUrlLink ) == 0 )
+        {
+        launchBrowser = EFalse;
+        }
+    // end THAA-82BEAZ
+
+    return launchBrowser;
+    }
+
+// ---------------------------------------------------------------------------
+// Launch the browser as a standalone app
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::LaunchBrowserL( const TDesC& aUrl )
+    {
+    CSchemeHandler* handler = CSchemeHandler::NewL( aUrl );
+    CleanupStack::PushL( handler );
+    handler->HandleUrlStandaloneL();
+    CleanupStack::PopAndDestroy( handler );
+    }
+
+void CFsEmailUiHtmlViewerContainer::PrepareBodyHtmlL( const TDesC& aFileName )
+    {
+
+    if( iMessage )
+        {
+        CFSMailMessagePart* htmlBodyPart = iMessage->HtmlBodyPartL();
+
+        if ( htmlBodyPart )
+            {
+            CleanupStack::PushL( htmlBodyPart );
+            // Copy html body part to email html file
+            CopyToHtmlFileL( *htmlBodyPart, aFileName );
+            CleanupStack::PopAndDestroy( htmlBodyPart );
+            }
+        else
+            {
+            CFSMailMessagePart* textBodyPart = iMessage->PlainTextBodyPartL();
+
+            if ( textBodyPart )
+                {
+                CleanupStack::PushL( textBodyPart );
+                // Copy html body part to email html file
+                ConvertToHtmlFileL( *textBodyPart, aFileName );
+                CleanupStack::PopAndDestroy( textBodyPart );
+                }
+            else
+                {
+                User::Leave( KErrNotFound );
+                }
+            }
+        }
+    }
+
+void CFsEmailUiHtmlViewerContainer::WriteEmptyBodyHtmlL( const TDesC& aFileName )
+    {
+    FUNC_LOG;
+    TFileName targetFileName;
+    targetFileName.Copy( iTempHtmlFolderPath );
+    targetFileName.Append( aFileName );
+    
+    RFile targetFile;
+    CleanupClosePushL( targetFile );
+    User::LeaveIfError( targetFile.Replace( iFs, targetFileName, EFileWrite ) );
+    User::LeaveIfError( targetFile.Write( KHTMLEmptyContent ) );   
+    CleanupStack::PopAndDestroy( &targetFile );    
+    }
+
+void CFsEmailUiHtmlViewerContainer::DisplayStatusIndicatorL(TInt aDuration)
+    {
+    FUNC_LOG;
+    TRect rect = CalcAttachmentStatusRect();
+    if(!iStatusIndicator)
+        {
+        iStatusIndicator  = CFreestyleEmailUiAknStatusIndicator::NewL( rect, this );
+        }  
+    CFbsBitmap* image = NULL;
+    CFbsBitmap* imageMask = NULL;
+    HBufC* statusText = NULL;
+    statusText = StringLoader::LoadL(R_FREESTYLE_EMAIL_UI_VIEWER_FETCHING_CONTENT_TEXT);
+    iAppUi.FsTextureManager()->ProvideBitmapL(EStatusTextureSynchronising, image, imageMask );
+    iStatusIndicator->ShowIndicatorL( image, imageMask, statusText, aDuration, ETrue );
+    }
+
+void CFsEmailUiHtmlViewerContainer::MailListModelUpdatedL()
+    {
+    FUNC_LOG;
+    UpdateOverlayButtons( IsVisible() );    
+    }
+
+
+void CFsEmailUiHtmlViewerContainer::WriteToFileL(const TDesC& aFileName, RBuf& aHtmlText)
+    {
+    _LIT( KCharsetUtf8, "UTF-8" );
+
+    HBufC8* content8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L( aHtmlText );
+    CleanupStack::PushL( content8 );        
+        
+    RFile targetFile;
+    CleanupClosePushL( targetFile );
+    User::LeaveIfError( targetFile.Replace( iFs, aFileName, EFileWrite ) );
+        
+    RBuf8 messageHeader;
+    TInt bufSize = KHtmlHeader1().Length() + KCharsetUtf8().Length() + KHtmlHeader2().Length();
+    messageHeader.CreateL( bufSize );
+    messageHeader.CleanupClosePushL();
+        
+    messageHeader.Append( KHtmlHeader1 );
+    messageHeader.Append( KCharsetUtf8 );
+    messageHeader.Append( KHtmlHeader2 );
+
+    RFileWriteStream fileStream( targetFile );
+    fileStream.PushL();
+    fileStream.WriteL( messageHeader.Ptr(), messageHeader.Length() );
+
+    TInt bufPos( 0 );
+    TInt bufTotalSize = content8->Size();
+
+    while ( bufPos < bufTotalSize )
+        {
+        TInt segmentLength = content8->Mid( bufPos ).Length();
+        fileStream.WriteL( content8->Mid( bufPos ).Ptr(), segmentLength );
+        bufPos += segmentLength;
+        }
+
+    fileStream.CommitL();
+
+    CleanupStack::PopAndDestroy( &fileStream );
+    CleanupStack::PopAndDestroy( &messageHeader );
+    CleanupStack::PopAndDestroy( &targetFile );
+    CleanupStack::PopAndDestroy( content8 );
+    }
+
+
+
+/******************************************************************************
+ * class PlainTextToHtmlConverter
+ ******************************************************************************/
+
+
+
+// -----------------------------------------------------------------------------
+// PlainTextToHtmlConverter::PlainTextToHtmlL
+// 
+// -----------------------------------------------------------------------------
+//
+void PlainTextToHtmlConverter::PlainTextToHtmlL(const TDesC& aPlainText, RBuf& aHtmlText)
+    {
+    const TInt KAllocSize = 1024;
+    
+    aHtmlText.Close();
+    aHtmlText.Create( aPlainText.Length() + KAllocSize );
+    
+    const TInt searhCases( CFindItemEngine::EFindItemSearchURLBin );
+    CFindItemEngine* itemEngine = CFindItemEngine::NewL( aPlainText, CFindItemEngine::TFindItemSearchCase( searhCases ) );
+    CleanupStack::PushL ( itemEngine );
+    
+    TInt currentPos = 0;
+    CFindItemEngine::SFoundItem item;
+    for ( TBool available(itemEngine->Item(item)); available; available=itemEngine->NextItem(item) )
+        {
+        if ( item.iStartPos < currentPos )
+            {
+            break; 
+            }
+        
+        TPtrC textPtr = aPlainText.Mid( currentPos, item.iStartPos-currentPos );
+        ConvertTextL( textPtr, aHtmlText );
+        
+        TPtrC urlPtr = aPlainText.Mid( item.iStartPos, item.iLength );
+        ConvertUrlL( urlPtr, aHtmlText);
+        
+        currentPos = item.iStartPos + item.iLength;
+        }
+    
+    TInt len = aPlainText.Length();
+    if ( currentPos < len )
+        {
+        TPtrC textPtr = aPlainText.Mid( currentPos );
+        ConvertTextL( textPtr, aHtmlText );
+        }
+    
+    CleanupStack::PopAndDestroy( itemEngine );
+    }
+
+
+// -----------------------------------------------------------------------------
+// PlainTextToHtmlConverter::ConvertTextL
+// 
+// -----------------------------------------------------------------------------
+//
+void PlainTextToHtmlConverter::ConvertTextL(const TDesC& aSource, RBuf& aTarget)
+    {
+    const TInt KAllocSize = 1024;
+    const TInt KEntitySize = 32;
+    
+    TInt count = aSource.Length();
+    for ( TInt i=0; i<count; i++ )
+        {
+        if ( aTarget.Length() + KEntitySize >= aTarget.MaxLength() )
+            {
+            aTarget.ReAllocL( aTarget.MaxLength() + KAllocSize );
+            }
+        
+        TText ch = aSource[i];
+        switch( ch )
+            {
+            case KSOH:  // end of line for IMAP and POP
+                aTarget.Append( KHtmlLineBreakCRLF );
+                break;
+            case KLF: // line feed
+            case KUnicodeNewLineCharacter:
+            case KUnicodeParagraphCharacter:
+                aTarget.Append(KHtmlLineBreak);
+                break;  
+            case KQuotation:
+                aTarget.Append( KHtmlQuotation );
+                break;
+            case KAmpersand:
+                aTarget.Append( KHtmlAmpersand );
+                break;
+            case KGreaterThan:
+                aTarget.Append( KHtmlGreaterThan );
+                break;
+            case KLessThan:
+                aTarget.Append( KHtmlLessThan );
+                break;
+            default:
+                aTarget.Append( ch );
+                break;
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// PlainTextToHtmlConverter::ConvertUrlL
+// 
+// -----------------------------------------------------------------------------
+//
+void PlainTextToHtmlConverter::ConvertUrlL(const TDesC& aSource, RBuf& aTarget)
+    {
+    _LIT( KSchemeDelimiter, "://" );
+    _LIT( KUrlFormat, "<a href=\"%S\">%S</a>" );
+    _LIT( KUrlFormatWithHttp, "<a href=\"http://%S\">%S</a>" );
+        
+    TPtrC format( KUrlFormat() );
+    if ( aSource.FindF( KSchemeDelimiter() ) == KErrNotFound ) 
+        {
+        format.Set( KUrlFormatWithHttp() );
+        }
+    
+    HBufC* formatBuffer = HBufC::NewLC( format.Length() + aSource.Length() * 2 );
+    formatBuffer->Des().Format( format, &aSource, &aSource );            
+    
+    TInt len = formatBuffer->Des().Length();
+    if ( aTarget.Length() + len >= aTarget.MaxLength() )
+        {
+        aTarget.ReAllocL( aTarget.MaxLength() + len );
+        }
+
+    aTarget.Append( *formatBuffer );
+        
+    CleanupStack::PopAndDestroy( formatBuffer );
+    }