emailuis/emailui/src/FreestyleEmailUiHtmlViewerContainer.cpp
changeset 0 8466d47a6819
child 1 12c456ceeff2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailuis/emailui/src/FreestyleEmailUiHtmlViewerContainer.cpp	Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,1104 @@
+/*
+* 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>
+
+//<cmail>
+#include "CFSMailMessage.h"
+//</cmail>
+#include <brctlinterface.h>
+#include <sysutil.h>
+
+
+#include "FreestyleEmailUiAppui.h"
+#include "FreestyleEmailUiUtilities.h"
+#include "FreestyleEmailUiHtmlViewerContainer.h"
+#include "FreestyleEmailUiHtmlViewerView.h"
+#include "FreestyleEmailUiShortcutBinding.h"
+
+#include "FreestyleMessageHeaderHTML.h"
+#include "FreestyleMessageHeaderURLEventHandler.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( KZDrive, "z:" );
+_LIT( KHtmlFlagFile, "html.flag" );
+
+// <cmail>
+// 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>\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");
+
+// </cmail>
+
+// ---------------------------------------------------------------------------
+// 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( CCoeEnv::Static()->FsSession() ),
+    iFirstTime( ETrue )
+    {
+    FUNC_LOG;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CFsEmailUiHtmlViewerContainer::~CFsEmailUiHtmlViewerContainer()
+    {
+    FUNC_LOG;
+    if ( iObservingDownload && iAppUi.DownloadInfoMediator() )
+        {
+        iAppUi.DownloadInfoMediator()->StopObserving( this );
+        }
+    iFile.Close();
+    iLinkContents.Close();
+    iMessageParts.Close();
+    delete iEventHandler;
+    delete iBrCtlInterface;
+    iConnection.Close();
+    iSocketServer.Close();
+    }
+
+// <cmail> Because of browser changes, followings must be performed before iAppUi.exit()
+void CFsEmailUiHtmlViewerContainer::PrepareForExit()
+    {
+    FUNC_LOG;
+    if ( iObservingDownload && iAppUi.DownloadInfoMediator() )
+        {
+        iAppUi.DownloadInfoMediator()->StopObserving( this );
+        iObservingDownload = EFalse;
+        }
+    delete iBrCtlInterface;
+    iBrCtlInterface = NULL;
+    iConnection.Close();
+    iSocketServer.Close();
+    }
+// </cmail>
+
+void CFsEmailUiHtmlViewerContainer::ConstructL()
+    {
+    FUNC_LOG;
+    
+    SetHtmlFolderPathL();
+    BaflUtils::EnsurePathExistsL( iFs, iHtmlFolderPath );
+    SetTempHtmlFolderPath();
+    BaflUtils::EnsurePathExistsL( iFs, iTempHtmlFolderPath );
+    SetHTMLResourceFlagFullName();
+    EnsureHTMLResourceL();
+    
+    CreateWindowL();
+    SetRect( iAppUi.ClientRect() );
+
+
+    TUint brCtlCapabilities = TBrCtlDefs::ECapabilityClientResolveEmbeddedURL |
+                              TBrCtlDefs::ECapabilityDisplayScrollBar |
+                              TBrCtlDefs::ECapabilityClientNotifyURL |
+                              TBrCtlDefs::ECapabilityLoadHttpFw |
+                              TBrCtlDefs::ECapabilityCursorNavigation;
+
+    // Set browsercontrol to whole screen
+    TRect rect( TPoint(), Size() );
+
+    iBrCtlInterface = CreateBrowserControlL( this, rect, brCtlCapabilities,
+        TBrCtlDefs::ECommandIdBase, NULL, this, this );
+
+    iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsEmbedded, ETrue );
+    iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsAutoLoadImages, ETrue );
+    iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsPageOverview, EFalse );
+    iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsTextWrapEnabled, ETrue );
+    iBrCtlInterface->SetBrowserSettingL( TBrCtlDefs::ESettingsFontSize, TBrCtlDefs::EFontSizeLevelLarger );
+
+    iEventHandler = CFreestyleMessageHeaderURLEventHandler::NewL( iAppUi, iView );
+    ActivateL();
+    }
+
+// 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 )
+    {
+    FUNC_LOG;
+    ASSERT( aMailMessage );
+    iMessage = aMailMessage;
+    
+    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
+    CFreestyleMessageHeaderHTML::ExportL( *iMessage, iFs, headerHtmlFile );
+    
+    // Remove all previously created files from temporary HTML folder
+    EmptyTempHtmlFolderL();
+
+    CFSMailMessagePart* htmlBodyPart = iMessage->HtmlBodyPartL();
+
+    if ( htmlBodyPart )
+        {
+        CleanupStack::PushL( htmlBodyPart );
+        
+        RFile htmlFile = htmlBodyPart->GetContentFileL();
+        CleanupClosePushL( htmlFile );
+        
+        // Copy html body part to email html file
+        CopyFileToHtmlFileL( htmlFile, KBodyHtmlFile, *htmlBodyPart );
+        
+        CleanupStack::PopAndDestroy( &htmlFile );
+        CleanupStack::PopAndDestroy( htmlBodyPart );
+        }
+    else
+        {
+        CFSMailMessagePart* textBodyPart = iMessage->PlainTextBodyPartL();;
+
+        if ( textBodyPart )
+            {
+            CleanupStack::PushL( textBodyPart );
+            //For now do not do any conversion just add start and end..Let browser display plain text as is
+            //Later need to refine this and add conversions
+            //htmlFile = textBodyPart->GetContentFileL();
+            //Need to get buffer in this case, file does not work
+            //HBufC* contentBuffer=HBufC::NewLC(textBodyPart->ContentSize());
+            
+            HBufC* contentBuffer=HBufC::NewLC(textBodyPart->FetchedContentSize());
+            TPtr bufPtr(contentBuffer->Des());
+            
+            textBodyPart->GetContentToBufferL(bufPtr,0);
+            HBufC8* contentBuffer8=HBufC8::NewLC(contentBuffer->Length());
+            
+            contentBuffer8->Des().Copy(*contentBuffer);         
+            CopyFileToHtmlFileL( *contentBuffer8, KBodyHtmlFile, *textBodyPart );
+            
+            CleanupStack::PopAndDestroy( contentBuffer8 );
+            CleanupStack::PopAndDestroy( contentBuffer );
+            CleanupStack::PopAndDestroy( textBodyPart ); 
+            }
+
+        }
+    // pass the emailHtmlFile to the browser for it to load
+    TPath emailHtmlFile;
+    emailHtmlFile.Copy( iHtmlFolderPath );
+    emailHtmlFile.Append( KMessageHtmlFile );
+    LoadContentFromFileL( emailHtmlFile );
+    }
+
+// ---------------------------------------------------------------------------
+// Reset content
+// ---------------------------------------------------------------------------
+//
+void CFsEmailUiHtmlViewerContainer::ResetContent()
+    {
+    FUNC_LOG;
+    if ( iBrCtlInterface )
+        {
+        TRAP_IGNORE( iBrCtlInterface->HandleCommandL( ( TInt )TBrCtlDefs::ECommandIdBase + 
+                                                      ( TInt )TBrCtlDefs::ECommandFreeMemory ) );
+        }
+    iFile.Close();
+    iLinkContents.Reset();
+    iMessageParts.Reset();
+    iMessage = NULL;
+    }
+
+// ---------------------------------------------------------------------------
+// From CCoeControl.
+// ---------------------------------------------------------------------------
+//
+CCoeControl* CFsEmailUiHtmlViewerContainer::ComponentControl( TInt aIndex ) const
+    {
+    FUNC_LOG;
+    switch ( aIndex )
+        {
+        case 0:
+            {
+            return iBrCtlInterface;
+            }
+        default:
+            {
+            return NULL;
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From CCoeControl.
+// ---------------------------------------------------------------------------
+//
+TInt CFsEmailUiHtmlViewerContainer::CountComponentControls() const
+    {
+    FUNC_LOG;
+    return 1;
+    }
+
+// ---------------------------------------------------------------------------
+// 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;
+    if ( iBrCtlInterface )
+        {
+        TRect rect = Rect();
+        iBrCtlInterface->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 )
+        {
+        retVal = iBrCtlInterface->OfferKeyEventL( aKeyEvent, 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 );
+            linkContent->HandleResolveComplete(
+                part->GetContentType(), KNullDesC(), content );
+            CleanupStack::PopAndDestroy( content );
+            CleanupStack::PopAndDestroy( &contentFile );
+            CleanupStack::PopAndDestroy( part );
+            }
+        if ( iMessage )
+            {
+            LoadContentFromMailMessageL( iMessage );
+            }
+        }
+    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;
+    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::CopyFileToHtmlFileL( RFile& aFile,
+    const TDesC& aFileName, CFSMailMessagePart& aHtmlBodyPart )
+    {
+    FUNC_LOG;
+    TFileName targetFileName;
+    targetFileName.Copy( iTempHtmlFolderPath );
+    targetFileName.Append( aFileName );
+
+    // Read content from given source file
+    HBufC8* content = ReadContentFromFileLC( aFile );
+
+    // Write content to target file
+    WriteContentToFileL( *content, targetFileName, aHtmlBodyPart );
+
+    CleanupStack::PopAndDestroy( content );
+    }
+// </cmail>
+
+// ---------------------------------------------------------------------------
+// Copies given buffer to HTML file
+// ---------------------------------------------------------------------------
+//
+// <cmail>
+void CFsEmailUiHtmlViewerContainer::CopyFileToHtmlFileL( const TDesC8& aBuffer,
+    const TDesC& aFileName, CFSMailMessagePart& aHtmlBodyPart )
+    {
+    FUNC_LOG;
+    TFileName targetFileName;
+    targetFileName.Copy( iTempHtmlFolderPath );
+    targetFileName.Append( aFileName );
+    
+    // Write content to target file
+    ConvertToHTML( aBuffer, targetFileName, aHtmlBodyPart );
+    }
+
+// ---------------------------------------------------------------------------
+// Reads given file content to buffer and return pointer to it
+// ---------------------------------------------------------------------------
+//
+HBufC8* CFsEmailUiHtmlViewerContainer::ReadContentFromFileLC( RFile& aFile )
+    {
+    FUNC_LOG;
+    TInt size = 0;
+    User::LeaveIfError( aFile.Size( size ) );
+    HBufC8* buffer = HBufC8::NewLC( size );
+    TPtr8 ptr = buffer->Des();
+    User::LeaveIfError( aFile.Read( ptr, size ) );
+    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 ) );
+
+        // Write ending metadata if needed
+        if ( modificationNeeded )
+            {
+            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 );
+        aEmbeddedLinkContent.HandleResolveComplete(
+            aAttachment.GetContentType(), KNullDesC(), content );
+        CleanupStack::PopAndDestroy( content );
+        CleanupStack::PopAndDestroy( &attachmentFile );
+        }
+    else
+        {
+        TPartData partData;
+        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
+// ---------------------------------------------------------------------------
+//
+// <cmail>
+void CFsEmailUiHtmlViewerContainer::ConvertToHTML( const TDesC8& aContent,
+    const TDesC& aFileName, CFSMailMessagePart& aHtmlBodyPart )
+    {
+    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 );
+        }
+    else
+        {
+        RFile targetFile;
+        CleanupClosePushL( targetFile );
+
+        User::LeaveIfError( targetFile.Replace( iFs, aFileName, EFileWrite ) );
+        
+	    	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 );
+
+
+        // Write the original content
+        for(int i=0;i<aContent.Length();i++)
+            {
+        	if( i==aContent.Length()-1 )
+        		{
+        		aContent.Mid( i,1 ).CompareC( _L8("\x01" ) )==0 ? 
+        		User::LeaveIfError( targetFile.Write( _L8("<br>") ) ):
+        		User::LeaveIfError( targetFile.Write( aContent.Mid(i,1) ) );
+        		}
+        	else
+        		{
+        		if(aContent.Mid( i,1 ).CompareC( _L8("\x01" ) )==0 ||
+        		aContent.Mid( i,2 ).CompareC( _L8("\x0D\x0A" ) )==0 ) 
+        			{
+        			User::LeaveIfError( targetFile.Write( _L8("<br>") ));
+        			}
+        		else
+      				{
+					User::LeaveIfError( targetFile.Write( aContent.Mid(i,1) ) );				                
+            		}
+          		}
+            }
+        INFO("Add end tags");
+        User::LeaveIfError( targetFile.Write( KHtmlEndTags ) );
+            
+
+        CleanupStack::PopAndDestroy( &targetFile );
+        }
+// </cmail>
+    }
+
+
+// ---------------------------------------------------------------------------
+// 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++ )
+        {
+        if ( ( contentTypeArray.MdcaPoint( i ).Find( 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) );
+        }   
+    }