javauis/eswt_akn/org.eclipse.ercp.swt.s60/native/src/swtbrowser.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 09 Jun 2010 09:34:07 +0300
branchRCL_3
changeset 34 71c436fe3ce0
parent 24 0fd27995241b
permissions -rw-r--r--
Revision: v2.1.28 Kit: 2010123

/*******************************************************************************
 * Copyright (c) 2007, 2010 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Nokia Corporation - S60 implementation
 *******************************************************************************/


#include <apgcli.h>
#include <charconv.h>
#include <eikappui.h>
#include <eiksbfrm.h>
#include <uri16.h>
#include <avkon.rsg>
#include <avkon.hrh>
#include <eikon.hrh>
#include <eswtcore.rsg>
#include <eikbtgpc.h>
#include <favouritesfile.h>
#include <favouritesdb.h>
#ifdef ESWT_ON_PUBLIC_SDK
#include <featureinfo.h>
#endif // ESW_ON_PUBLIC_SDK

#include "swtbrowserapsettingshandler.h"
#include "eswtmobileextensions.h"
#include "swtbrowserdialogsproviderproxy.h"
#include "swtbrowseraputils.h"
#include "swtbrowseractiveapdb.h"
#include "swtbrowser.h"
#include "swtbrowsercontainer.h"
#include "swtbrowserloadeventobserver.h"
#include "swtbrowserlinkresolver.h"
#include "swtbrowserstatechangeobserver.h"
#include "swtbrowserspecialloadobserver.h"
#include "swtbrowserdialogsproviderproxy.h"
#include "swtbrowsersoftkeysobserver.h"
#include "swtbrowserpreferences.h"
#include "swtbrowserconnectionmanager.h"
#include "swtuiutils.h"


// Use the same error codes as browsrNG
const TInt KBrsrMalformedUrl = -26018;
const TInt KBrsrUnknownScheme = -26026;
const TInt KMSKCbaButtonIndex = 2;

// A temporary directory location for widgetExtensions
_LIT(KWidgetPath, "C:\\");

// Default URL
_LIT(KUrl, "data:");

typedef CBrCtlInterface*(*FuncPtr_CreateBrowserControlL)(CCoeControl* aParent, TRect aRect,
        TUint aBrCtlCapabilities, TUint aCommandIdBase,
        MBrCtlSoftkeysObserver* aBrCtlSoftkeysObserver,
        MBrCtlLinkResolver* aBrCtlLinkResolver,
        MBrCtlSpecialLoadObserver* aBrCtlSpecialLoadObserver,
        MBrCtlLayoutObserver* aBrCtlLayoutObserver,
        MBrCtlDialogsProvider* aBrCtlDialogsProvider,
        MBrCtlWindowObserver* aBrCtlWindowObserver,
        MBrCtlDownloadObserver* aBrCtlDownloadObserver);


// ======== MEMBER FUNCTIONS ========


// -----------------------------------------------------------------------------
// Constructor. Scrollbar flags are removed before aStyle is passed to the CSwtComposite.
// So, supper class does not know anything about the existence of scrollbar.
// -----------------------------------------------------------------------------
//
CSwtBrowser::CSwtBrowser(MSwtDisplay& aDisplay, TSwtPeer aPeer, MSwtComposite* aParent
                         , TInt aStyle,TBool aVisibility, TBool aDimmed)
        : CSwtComposite(aDisplay, aPeer, aParent,
                        aStyle & ~KSwtStyleHScroll & ~KSwtStyleVScroll, aVisibility, aDimmed)
        , iBrowserLevelStyle(aStyle)
        , iFeatureManager(EFalse)
{
}

// ---------------------------------------------------------------------------
// 2nd phase constructor
// ---------------------------------------------------------------------------
//
void CSwtBrowser::ConstructL()
{
    CSwtComposite::ConstructL();
    SetBlank(); // needs to draw border at least
    SetComponentsToInheritVisibility(ETrue);
}

// ---------------------------------------------------------------------------
// Separated second phase constructor, specially for the construction of CBrCtlInterface
// ---------------------------------------------------------------------------
//
void CSwtBrowser::ConstructBrowserL(TBool aVisibility)
{
    // Init FavouritesSess
    User::LeaveIfError(iFavouritesSess.Connect());

    // Init FeatureManager
    CSwtLafFacade::InitFeatureManagerL();
    iFeatureManager = ETrue;

    // Init active ap database
    iActiveApDb = CSwtBrowserActiveApDb::NewL();

    // Creating object to hold application settings
    iPreferences = CSwtBrowserPreferences::NewL(*iActiveApDb, *this);
    iPreferences->AddObserverL(this);

    iConnection = new(ELeave) CSwtBrowserConnectionManager(&iActiveApDb->CommsDb(), *this);

    // Set AP to be a default one
    SetRequestedAP(Preferences().DefaultAccessPoint());

    // Create Observers
    iLoadEventObserver = new(ELeave) CSwtBrowserLoadEventObserver(this , iPeer);
    iLinkResolver = new(ELeave) CSwtBrowserLinkResolver(this , iPeer);
    iStateChangeObserver = new(ELeave) CSwtBrowserStateChangeObserver(this, iPeer);
    iSpecialLoadObserver = CSwtBrowserSpecialLoadObserver::NewL(this);
    iDialogsProviderProxy = CSwtBrowserDialogsProviderProxy::NewL(iLoadEventObserver);
    iSoftkeysObserver = new(ELeave) CSwtBrowserSoftkeysObserver(this);

    // BrCtlCapabilities
    TUint capabilityFlags = TBrCtlDefs::ECapabilityLoadHttpFw
                            | TBrCtlDefs::ECapabilityConfirmDownloads
                            | TBrCtlDefs::ECapabilitySavedPage
                            | TBrCtlDefs::ECapabilityUseDlMgr
                            | TBrCtlDefs::ECapabilityCursorNavigation
                            | TBrCtlDefs::ECapabilityFavicon
                            | TBrCtlDefs::ECapabilityToolBar
                            | TBrCtlDefs::ECapabilityFitToScreen
#ifdef RD_JAVA_S60_RELEASE_9_2
                            | TBrCtlDefs::ECapabilityPinchZoom
#endif
                            ;

    if ((iBrowserLevelStyle | KSwtStyleHScroll) || (iBrowserLevelStyle |  KSwtStyleVScroll))
    {
        capabilityFlags = capabilityFlags | TBrCtlDefs::ECapabilityDisplayScrollBar;
    }
    if (Preferences().UiLocalFeatureSupported(
                CSwtLafFacade::GetConstant(CSwtLafFacade::EBrowserGraphicalPage)))
    {
        capabilityFlags = capabilityFlags | TBrCtlDefs::ECapabilityGraphicalPage;
    }
    if (Preferences().UiLocalFeatureSupported(
                CSwtLafFacade::GetConstant(CSwtLafFacade::EBrowserGraphicalPage)) &&
            Preferences().UiLocalFeatureSupported(
                CSwtLafFacade::GetConstant(CSwtLafFacade::EBrowserGraphicalHistory)))
    {
        capabilityFlags = capabilityFlags | TBrCtlDefs::ECapabilityGraphicalHistory;
    }
    if (Preferences().UiLocalFeatureSupported(
                CSwtLafFacade::GetConstant(CSwtLafFacade::EBrowserAutoFormFill)))
    {
        capabilityFlags = capabilityFlags | TBrCtlDefs::ECapabilityAutoFormFill;
    }
    if (Preferences().UiLocalFeatureSupported(
                CSwtLafFacade::GetConstant(CSwtLafFacade::EBrowserAccessKeys)))
    {
        capabilityFlags = capabilityFlags | TBrCtlDefs::ECapabilityAccessKeys;
    }

    // Create browser container.
    TRect rect=CalcBrowserRect();
    iContainer = CSwtBrowserContainer::NewL(*this);
    iContainer->SetRect(rect);
    iContainer->SetComponentsToInheritVisibility(ETrue);

    TLibraryFunction dllEntry = UiUtils().BrowserDllEntryL();
    FuncPtr_CreateBrowserControlL fptr = (FuncPtr_CreateBrowserControlL) dllEntry;

    iBrCtlInterface = (*fptr)(iContainer,
                              iContainer->Rect(),
                              capabilityFlags,
                              static_cast < TUint >(TBrCtlDefs::ECommandIdBase),    // command base
                              iSoftkeysObserver,
                              iLinkResolver,
                              iSpecialLoadObserver,
                              NULL,
                              iDialogsProviderProxy,
                              NULL,
                              NULL);

    if (!iBrCtlInterface)
    {
        User::Leave(KErrNoMemory);
    }

    TPtrC selfDownloadContentTypes = Preferences().SelfDownloadContentTypesL();
    iBrCtlInterface->SetSelfDownloadContentTypesL(selfDownloadContentTypes);

    // Add two more observers
    iBrCtlInterface->AddLoadEventObserverL(iLoadEventObserver);
    iBrCtlInterface->AddStateChangeObserverL(iStateChangeObserver);

    // Update browser global settings according to values stored in preferences
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsAutoLoadImages, Preferences().AutoLoadImages());
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsDisableFlash, !Preferences().AutoLoadImages());
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsEmbedded , EFalse);
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsCookiesEnabled, Preferences().Cookies());
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsECMAScriptEnabled, Preferences().Ecma());
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsIMEINotifyEnabled, Preferences().IMEINotification());
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsSendRefererHeader, Preferences().SendReferrer());
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsSecurityWarnings, Preferences().HttpSecurityWarnings());
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsPageOverview, Preferences().PageOverview());
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsBackList, Preferences().BackList());
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsAutoRefresh, Preferences().AutoRefresh());
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsAutoFormFillEnabled, Preferences().FormDataSaving());

    // Update browser local settings according to values stored in preferences
    const TPreferencesValues& pref = iPreferences->AllPreferences();
    iFontSize = pref.iFontSize;
    iTextWrap = pref.iTextWrap;
    iEncoding = pref.iEncoding;
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsFontSize, iFontSize);
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsTextWrapEnabled, iTextWrap);
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsCharacterset, iEncoding);
    iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsLaunchAppUid, iDisplay.ApplicationUid());

    if (pref.iZoomMin < pref.iZoomMax && pref.iZoomDef >= pref.iZoomMin && pref.iZoomDef <= pref.iZoomMax)
    {
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsZoomLevelMin, pref.iZoomMin);
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsZoomLevelMax, pref.iZoomMax);
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsZoomLevelDefault, pref.iZoomDef);
    }
    else
    {
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsZoomLevelMin, 10);
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsZoomLevelMax, 200);
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsZoomLevelDefault, 100);
    }

    // WidgetExtension needs a valid base path.
    // Base path would be used to write preferences on Widget runtime context but
    // when embedded into eSWT it does not really write any data. The base path still
    // needs to be provided to avoid any crashes during exit.
    MWidgetExtension* widgetExtension = iBrCtlInterface->CreateWidgetExtensionL(*this);
    widgetExtension->SetParamL(TBrCtlDefs::EWidgetBasePath, KWidgetPath);

    iBrCtlInterface->MakeVisible(aVisibility);
    iContainer->MakeVisible(aVisibility);
    MakeVisible(aVisibility);
    ActivateL();

    if (IsFocused())
    {
        CCoeControl::SetFocus(EFalse, ENoDrawNow);
    }
    ASSERT(!IsFocused());

    iStartedUp = ETrue; // Inddicates Browser is ready for using
}

// ---------------------------------------------------------------------------
// 1st and 2nd phase constructor wrapper.
// ---------------------------------------------------------------------------
//
CSwtBrowser* CSwtBrowser::NewL(MSwtDisplay& aDisplay, TSwtPeer aPeer,
                               MSwtComposite& aParent, TInt aStyle)
{
    CCoeControl& parentCtrl = aParent.Control()->CoeControl();

    CSwtBrowser* self = new(ELeave) CSwtBrowser(aDisplay, aPeer, &aParent, aStyle,
            parentCtrl.IsVisible(), parentCtrl.IsDimmed());
    CleanupStack::PushL(self);
    self->ConstructL();
    self->UiUtils().NotifyNewBrowserCreated();
    self->ConstructBrowserL(parentCtrl.IsVisible());
    self->InitControlBaseL();
    CleanupStack::Pop(self);
    return self;
}

// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
//
CSwtBrowser::~CSwtBrowser()
{
    if (iFeatureManager)
    {
        CSwtLafFacade::UnInitFetureManager();
        iFeatureManager = EFalse;
    }

    CSwtBrowserConnectionManager* inetconman = static_cast <CSwtBrowserConnectionManager*>(iConnection);
    delete inetconman;

    if (iPreferences)
    {
        iPreferences->RemoveObserver(this);
        delete iPreferences;
    }

    delete iActiveApDb;
    iFavouritesSess.Close();

    if (iBrCtlInterface)
    {
        iBrCtlInterface->RemoveLoadEventObserver(iLoadEventObserver);
        iBrCtlInterface->RemoveStateChangeObserver(iStateChangeObserver);
        delete iBrCtlInterface;
    }

    delete iContainer;

    delete iLoadEventObserver;
    delete iLinkResolver;
    delete iStateChangeObserver;
    delete iSpecialLoadObserver;
    delete iDialogsProviderProxy;
    delete iSoftkeysObserver;
}

CBrCtlInterface& CSwtBrowser::BrCtlInterface() const
{
    ASSERT(iBrCtlInterface);
    return *iBrCtlInterface;
}


CSwtBrowserActiveApDb& CSwtBrowser::ActiveApDb() const
{
    ASSERT(iActiveApDb);
    return *iActiveApDb;
}

MBrowserPreferences& CSwtBrowser::Preferences() const
{
    ASSERT(iPreferences);
    return *iPreferences;
}

CSwtBrowserLoadEventObserver& CSwtBrowser::LoadObserver() const
{
    ASSERT(iLoadEventObserver);
    return *iLoadEventObserver;
}

CSwtBrowserSpecialLoadObserver& CSwtBrowser::SpecialLoadObserver() const
{
    ASSERT(iSpecialLoadObserver);
    return *iSpecialLoadObserver;
}

MSwtDisplay& CSwtBrowser::Display() const
{
    return iDisplay;
}

void CSwtBrowser::UpdateCbaL()
{
    if (StartedUp())
    {
        CEikButtonGroupContainer& cba = iDisplay.UiUtils().Cba();

        TBrCtlDefs::TBrCtlElementType elementtype =
            iBrCtlInterface->FocusedElementType();
        // Cba2 must set to cancel and command observer must be added
        // when a inputbox is actvated becasue browser supposes the concel command is there
        // and will send a simulated cba2 event to deactivate input box
        if ((elementtype == TBrCtlDefs::EElementActivatedInputBox)
                || (elementtype == TBrCtlDefs::EElementActivatedObjectBox))
        {
            if (iCbaState != CSwtBrowser::EActivatedInputBox)
            {
                iCbaState = CSwtBrowser::EActivatedInputBox;
                HBufC* label = iEikonEnv->AllocReadResourceL(R_SWT_SOFTKEY_TEXT_CANCEL);
                CleanupStack::PushL(label);
                iDisplay.CommandArranger()->UpdateRightSoftkeyCommandAndObserver(
                    KSwtCommandBaseId + EAknSoftkeyCancel, *label, *this);
                CleanupStack::Pop(label);
            }
            return;
        }

        if (iCbaState != CSwtBrowser::EDefault)
        {
            iCbaState = CSwtBrowser::EDefault;
            iDisplay.CommandArranger()->RefreshCba();
        }
    }
}

#ifdef RD_SCALABLE_UI_V2
// ---------------------------------------------------------------------------
// Originated from CSwtBrowserContainer, not CSwtShell.
// ---------------------------------------------------------------------------
//
void CSwtBrowser::HandlePointerEventL(const TPointerEvent& aPointerEvent)
{
    iHandlingPointerEv = ETrue;

    if (!iDisplay.RevertPointerEvent())
    {
#ifdef RD_JAVA_S60_RELEASE_9_2
        // From parent Shell coordinates to CSwtBrowserContainer coordinates
        if (aPointerEvent.AdvancedPointerEvent())
        {
            TAdvancedPointerEvent event = *(static_cast<const TAdvancedPointerEvent*>(&aPointerEvent));
            event.iPosition -= Rect().iTl;
            iBrCtlInterface->HandlePointerEventL(event);
        }
        else
#endif
        {
            TPointerEvent event = *(static_cast<const TPointerEvent *>(&aPointerEvent));
            event.iPosition -= Rect().iTl;
            iBrCtlInterface->HandlePointerEventL(event);
        }
    }

    iHandlingPointerEv = EFalse;

    PostMouseEventL(aPointerEvent);
}
#endif

// ---------------------------------------------------------------------------
// This function only gets called on device
// ---------------------------------------------------------------------------
//
TBool CSwtBrowser::StartPreferencesViewL()
{
    TUint32 defaultAp = iPreferences->DefaultAccessPoint();
    TBool retVal(EFalse);
    if (defaultAp == KWmlNoDefaultAccessPoint)
    {
        // Showing AP selection dialog
        CSwtBrowserApSettingsHandler* ApUi = NULL;
        ApUi = CSwtBrowserApSettingsHandler::NewLC();

        TRAPD(err, ApUi->RunSettingsL(defaultAp, defaultAp));
        CleanupStack::PopAndDestroy(ApUi);
        if (err)
        {
            defaultAp = KWmlNoDefaultAccessPoint;
        }
        iPreferences->SetDefaultAccessPointL(defaultAp);
        defaultAp = iPreferences->DefaultAccessPoint(); //get it
    }
    if (defaultAp != KWmlNoDefaultAccessPoint)
    {
        SetRequestedAP(defaultAp);
        retVal = ETrue;
    }
    return retVal;
}

TBool CSwtBrowser::IsConnecting() const
{
    return (LoadObserver().LoadState() != CSwtBrowserLoadEventObserver::ELoadStateIdle);
}

void CSwtBrowser::SetRequestedAP(TInt aAp)
{
    iRequestedAp = aAp;
}

TBool CSwtBrowser::StartedUp() const
{
    return iStartedUp;
}

TUint32 CSwtBrowser::RequestedAp() const
{
    return iRequestedAp;
}

void CSwtBrowser::FetchSavedDeckL(TInt aUid)
{
    _LIT(KSavedPage,  "savedpage://");
    _LIT(KUidFormat, "%d");
    const TInt KUidFullMaxLength = 22;// max uid length, containing length of KSavedPage
    const TInt KUidMaxLength = 10;// max uid length, not containing length of KSavedPage


    User::LeaveIfError(iFavouritesSess.Connect());
    RFavouritesDb db;
    User::LeaveIfError(db.Open(iFavouritesSess, KBrowserSavedPages));
    CleanupClosePushL<RFavouritesDb>(db);
    RFavouritesFile favFile;
    if (favFile.Open(db, aUid) == KErrNone)
    {
        TInt siz;
        favFile.Size(siz);
        HBufC8* buf  = HBufC8::NewLC(siz);
        TPtr8 des = buf->Des();
        TInt err = favFile.Read(des);
        if (err == KErrNone)
        {
            TBuf < KUidFullMaxLength > uidText;
            TBuf < KUidMaxLength > uid ;
            uid.Format(KUidFormat, aUid);
            uidText.Copy(KSavedPage);
            uidText.Append(uid);
            HBufC16* copyBuf = HBufC::NewLC(siz);
            copyBuf->Des().Copy(des);
            LoadObserver().DoStartLoad(CSwtBrowserLoadEventObserver::ELoadUrlTypeOther);
            BrCtlInterface().LoadSavedPageL(uidText , *copyBuf);
            CleanupStack::PopAndDestroy(copyBuf);
        }
        favFile.Close();
        CleanupStack::PopAndDestroy(buf);
    }
    CleanupStack::PopAndDestroy(); // db
}

MBrowserConnection& CSwtBrowser::Connection() const
{
#if defined( _DEBUG )
    _LIT(KAppName, "eSwtBrowser");
#endif
    __ASSERT_DEBUG(iConnection, User::Panic(KAppName, 0));
    return *iConnection;
}

void CSwtBrowser::HandlePreferencesChangeL(TPreferencesEvent aEvent, TPreferencesValues& aValues,
        TBrCtlDefs::TBrCtlSettings aSettingType)
{
    switch (aEvent)
    {
    case EPreferencesActivate:
    {
        // Provide settings
        aValues.iFontSize = iFontSize;
        aValues.iTextWrap = iTextWrap;
        aValues.iEncoding = iEncoding;
        break;
    }
    case EPreferencesDeactivate:
    {
        // Save preferences and notify Browser Control
        UpdateLocalPreferencesL(aValues);
        break;
    }
    case EPreferencesItemChange:
    {
        // All preferences changes should notify the Browser Control
        UpdateGlobalPreferencesL(aSettingType);

        // Change the local setting to the changed setting.
        UpdateLocalPreferencesL(aValues);
        break;
    }
    default:
        break;
    }
}

// ---------------------------------------------------------
// The funtion just posts a callback event.
// Loading URL will be started by callback event framework
// ---------------------------------------------------------
//
TBool CSwtBrowser::BackL()
{
    HBufC* url = iEikonEnv->AllocReadResourceAsDes16LC(R_SWT_URL_BACK);
    iLoadEventObserver->SetUrlL(*url);
    iDisplay.PostLocationChangingEventL(iPeer, *this, ETrue, ETrue, *url, ESwtBrGoBack);
    CleanupStack::PopAndDestroy(url);
    return ETrue;
}

// ---------------------------------------------------------
// The funtion just posts a callback event. Loading URL will be started by callback event framework
// ---------------------------------------------------------
//
TBool CSwtBrowser::ForwardL()
{
    HBufC* url = iEikonEnv->AllocReadResourceAsDes16LC(R_SWT_URL_FORWARD);
    iLoadEventObserver->SetUrlL(*url);
    iDisplay.PostLocationChangingEventL(iPeer, *this, ETrue, ETrue, *url, ESwtBrGoForward);
    CleanupStack::PopAndDestroy(url);
    return ETrue;
}

// ---------------------------------------------------------
// The URL is available only when PageInfo is available
// ---------------------------------------------------------
//
HBufC* CSwtBrowser::GetUrlL()
{
    HBufC * urlText = NULL;
    HBufC * url = iBrCtlInterface->PageInfoLC(TBrCtlDefs::EPageInfoUrl);

    if (url)
    {
        urlText = url->AllocL(); // Not push to CleanupStack becasue of no more leave function
    }
    else
    {
        urlText = iEikonEnv->AllocReadResourceAsDes16L(R_SWT_NO_NAME);
    }
    CleanupStack::PopAndDestroy(url);
    return urlText;
}

TBool CSwtBrowser::IsBackEnabled() const
{
    return  iBrCtlInterface->NavigationAvailable(TBrCtlDefs::ENavigationBack);
}

TBool CSwtBrowser::IsForwardEnabled() const
{
    return  iBrCtlInterface->NavigationAvailable(TBrCtlDefs::ENavigationForward);
}

void CSwtBrowser::RefreshL()
{
    HBufC * url = iBrCtlInterface->PageInfoLC(TBrCtlDefs::EPageInfoUrl);

    // Crashes on Avkon side when no correct URL is set
    if (*url != KUrl)
    {
        iBrCtlInterface->HandleCommandL(TBrCtlDefs::ECommandReload +
                                        TBrCtlDefs::ECommandIdBase);
    }

    CleanupStack::PopAndDestroy(url);
}

void CSwtBrowser::StopL()
{
    CancelFetchL();
}

TBool CSwtBrowser::SetTextL(const TDesC& aHtml)
{
    // convert html from 16bit to 8bit
    TInt htmlSize = aHtml.Size();
    HBufC8* html = HBufC8::NewLC(htmlSize);
    TPtr8  ptr = html->Des();
    ptr.Copy(aHtml);

    _LIT8(KDataType, "text/html");
    TDataType dataType(KDataType());

    TUid uid;
    //uid.iUid = KCharacterSetIdentifierIso88591;
    uid.iUid = iEncoding;

    HBufC * url = iEikonEnv->AllocReadResourceAsDes16LC(R_SWT_URL_SETTEXT);
    iLoadEventObserver->SetUrlL(*url);
    CleanupStack::PopAndDestroy(url);

    iBrCtlInterface->LoadDataL(KUrl, *html, dataType, uid);

    CleanupStack::PopAndDestroy(html);
    return ETrue;
}

TBool CSwtBrowser::SetUrlL(const TDesC&  aUrl)
{
    TUriParser uriParser;
    TInt err = uriParser.Parse(aUrl);
    if (err || !aUrl.Length())
    {
        iCoeEnv->HandleError(KBrsrUnknownScheme);
        return EFalse;
    }


    iLoadEventObserver->SetUrlL(aUrl);

    iDisplay.PostLocationChangingEventL(iPeer, *this, ETrue, ETrue, aUrl, ESwtBrLoadUrl);

    return ETrue;
}

void CSwtBrowser::DoSetUrlL(const TDesC&  aUrl,
                            TSwtBrCallBackOperationType aOperationType)
{

    switch (aOperationType)
    {
    case ESwtBrLoadUrl: // load a Url
        FetchL(aUrl);  // FetchL will notify  load event observer
        break;
    case ESwtBrGoBack: // go back
        iLoadEventObserver->DoStartLoad(
            CSwtBrowserLoadEventObserver::ELoadUrlTypeOther);
        iBrCtlInterface->HandleCommandL(TBrCtlDefs::ECommandBack
                                        + TBrCtlDefs::ECommandIdBase);
        break;
    case ESwtBrGoForward: //go forward
        iLoadEventObserver->DoStartLoad(
            CSwtBrowserLoadEventObserver::ELoadUrlTypeOther);
        iBrCtlInterface->HandleCommandL(TBrCtlDefs::ECommandForward
                                        + TBrCtlDefs::ECommandIdBase);
        break;
    case ESwtBrDoNothing:// do nothing
        break;
    default:
        ASSERT(EFalse);
    }
}

void CSwtBrowser::HandleFreeRamEventL(TInt aEventType)
{

    if (aEventType ==  CSwtLafFacade::GetConstant(CSwtLafFacade::EBrowserFreeRam))
    {
        BrCtlInterface().HandleCommandL(
            (TInt)TBrCtlDefs::ECommandFreeMemory + (TInt)TBrCtlDefs::ECommandIdBase);
    }
    else if (aEventType == CSwtLafFacade::GetConstant(CSwtLafFacade::EBrowserMemoryGood))
    {
        BrCtlInterface().HandleCommandL(
            (TInt)TBrCtlDefs::ECommandMemoryGood + (TInt)TBrCtlDefs::ECommandIdBase);
    }
}

void CSwtBrowser::DoDelete()
{
    UiUtils().GarbageCollect(*this);
}

TSwtPeer CSwtBrowser::Dispose()
{
    if (Fetching())
    {
        TRAP_IGNORE(CancelFetchL());
    }

    if (iBrCtlInterface)
    {
        if (IsFocused())
        {
            CoeControl().SetFocus(EFalse);
            TRAP_IGNORE(iBrCtlInterface->HandleCommandL(
                            TBrCtlDefs::ECommandLoseFocus + TBrCtlDefs::ECommandIdBase));
        }
    }

    //if( !iBrCtlInterface->OkToExit() )
    //{
    //return;
    //ASSERT( EFalse );
    //}

    if (iConnection)
    {
        TRAP_IGNORE(iBrCtlInterface->HandleCommandL(
                        TBrCtlDefs::ECommandDisconnect + TBrCtlDefs::ECommandIdBase));
        iConnection->Disconnect();
    }
    iBrCtlInterface->ClearCache();

    // If being garbage collected, must hide. If disposing for real, avoid cursor crash.
    MakeVisible(EFalse);

    return CSwtComposite::Dispose();
}

HBufC* CSwtBrowser::MSKLabelL() const
{
    return KNullDesC().AllocL();
}

TBool CSwtBrowser::IsKeyUsed(TUint aKeyCode) const
{
    if (aKeyCode == EKeyCBA1 || aKeyCode == EKeyCBA2)
    {
        return EFalse;
    }
    return ETrue;
}

TBool CSwtBrowser::CbaButtonIsUsed(TInt aCbaButtonIndex) const
{
    if (aCbaButtonIndex == KMSKCbaButtonIndex)
    {
        return ETrue;
    }

    return EFalse;
}

TBool CSwtBrowser::IsFocusable(TInt aReason /*=KSwtFocusByApi*/) const
{
    // Don't want CSwtComposite's focusability behavior.
    return ASwtScrollableBase::IsFocusable(aReason);
}

MSwtBrowser* CSwtBrowser::BrowserInterface() const
{
    const MSwtBrowser* browser = this;
    return const_cast<MSwtBrowser*>(browser);
}

MSwtComposite* CSwtBrowser::Composite()
{
    return this;
}

TSize CSwtBrowser::ComputeSizeL(TInt aWHint, TInt aHHint)
{

    TSize computeSize(0, 0);

    if (!iBrCtlInterface)
    {
        if (aWHint != KSwtDefault)
        {
            computeSize.iWidth = aWHint;
        }
        if (aHHint != KSwtDefault)
        {
            computeSize.iHeight = aHHint;
        }
        return computeSize;
    }

    // Start from content size
    computeSize = iBrCtlInterface->ContentSize();

    // Update according to minimum size
    TSize minimumSize = iBrCtlInterface->MinimumSize();
    if (computeSize.iWidth < minimumSize.iWidth)
    {
        computeSize.iWidth = minimumSize.iWidth;
    }
    if (computeSize.iHeight < minimumSize.iHeight)
    {
        computeSize.iHeight = minimumSize.iHeight;
    }

    // Update according to top shell size
    TSize shellSize = iDisplay.UiUtils().GetControlTopShell(*this).Control()->
                      ClientRect().Size();
    if (computeSize.iWidth > shellSize.iWidth)
    {
        computeSize.iWidth = shellSize.iWidth;
    }
    if (computeSize.iHeight > shellSize.iHeight)
    {
        computeSize.iHeight = shellSize.iHeight;
    }

    // Update to hints suggested size
    if (aWHint != KSwtDefault)
    {
        computeSize.iWidth = aWHint;
    }
    if (aHHint != KSwtDefault)
    {
        computeSize.iHeight = aHHint;
    }

    return computeSize;
}

// ----------------------------------------------------
// Browser rect = container rect - border - scrollbars
// ----------------------------------------------------
//
TRect CSwtBrowser::CalcBrowserRect()
{
    // Calculate rect relative to browser's parent
    TRect inclusiveRect(BorderInnerRect());
    TRect clientRect(SbInnerRect(inclusiveRect));
    return clientRect;
}

void CSwtBrowser::FetchL(const TDesC& aUrl,
                         CSwtBrowserLoadEventObserver::TBrowserLoadUrlType aUrlType)
{
    TFavouritesWapAp ap;
    ap.SetDefault();
    FetchL(aUrl, KNullDesC, KNullDesC, ap, aUrlType);
}

void CSwtBrowser::FetchL(const TDesC& aUrl, const TDesC& aUsername,
                         const TDesC& aPassword, const TFavouritesWapAp& aAccessPoint,
                         CSwtBrowserLoadEventObserver::TBrowserLoadUrlType aUrlType)
{
    // Cancel the previous fetch if there is any
    if (Fetching())
    {
        CancelFetchL();
    }

    TUriParser uriParser;
    TInt err = uriParser.Parse(aUrl);
    if (err || !aUrl.Length())
    {
        return iCoeEnv->HandleError(KBrsrUnknownScheme);
    }
    HBufC* resultUrlBuf = CreateFullUrlLC(aUrl, aUsername, aPassword);

    // Set requested ap in following order
    // 1. from user provided ap
    // 2. from preference


    if (aAccessPoint.IsNull() || aAccessPoint.IsDefault()
            || (!IsValidAPFromParamL(aAccessPoint.ApId())))
    {
        // user didn't provide volid ap
        // use default ap from preferences
        iRequestedAp = Preferences().DefaultAccessPoint();
    }
    else
    {
        // user's ap seems good
        iRequestedAp = aAccessPoint.ApId();
    }

    // check validity of the requested ap
    // set always ask mode on if request ap is invalid

    // define dummy ap
    const TInt KDummyAp(2);
    const TInt KDummyApId(2);

#ifndef __WINSCW__
    TUint32 IAPid(iRequestedAp);
    if (iRequestedAp == KWmlNoDefaultAccessPoint)
    {
        // no defined ap
        // do not start ap setting dialog here becasue network connection is not alwasys needed,
        // e.g. loading url locally

        // set always ask mode
        iPreferences->SetAccessPointSelectionModeL(
            EWmlSettingsAccessPointSelectionModeAlwaysAsk);
        // just set dummy id not to let Ap engine or Ap Util to leave
        iRequestedAp = KDummyAp;
        IAPid = KDummyApId;
    }
    else
    {
        // there is a defined ap
        CCommsDatabase& db = iActiveApDb->CommsDb();
        CSwtBrowserApUtils* apUtils = CSwtBrowserApUtils::NewL(db);
        CleanupStack::PushL(apUtils);
        IAPid = apUtils->IapIdFromWapIdL(iRequestedAp);
        CleanupStack::PopAndDestroy(apUtils);
        // set user selection mode
        iPreferences->SetAccessPointSelectionModeL(
            EWmlSettingsAccessPointSelectionModeUserDefined);
    }
#else
    // On WINS, don't start setting dialog here
    // as the connection manager will popup a selection dialog
    // just use dummy id
    iRequestedAp = KDummyAp;
    TUint32 IAPid = KDummyApId;
    // set always ask mode
    iPreferences->SetAccessPointSelectionModeL(
        EWmlSettingsAccessPointSelectionModeAlwaysAsk);
#endif //__WINSCW__

    //Load Url
    LoadObserver().DoStartLoad(aUrlType);   //notify load observer
    if (aUrlType == CSwtBrowserLoadEventObserver::ELoadUrlTypeSavedDeck)
    {
        TRAP(err, BrCtlInterface().LoadUrlL(resultUrlBuf->Des()
                                            , IAPid, TBrCtlDefs::ECacheModeNoCache));
    }
    else
    {
        TRAP(err, BrCtlInterface().LoadUrlL(resultUrlBuf->Des(), IAPid));
    }
    CleanupStack::PopAndDestroy(resultUrlBuf);

    if (err != KErrNone)
    {
        CancelFetchL();
    }

    //Handle errors
    switch (err)
    {
    case KErrNotFound:
        iCoeEnv->HandleError(KBrsrMalformedUrl);
        break;
    case KErrNone:
        break;
    default:
        User::Leave(err);    // pass error code
        break;
    }
}

TBool CSwtBrowser::Fetching() const
{
    return (LoadObserver().LoadState() != CSwtBrowserLoadEventObserver::ELoadStateIdle);
}

void CSwtBrowser::CancelFetchL(TBool aIsUserInitiated /*= EFalse*/)
{
    LoadObserver().DoEndLoad(aIsUserInitiated);   // notify load observer
    iBrCtlInterface->HandleCommandL(TBrCtlDefs::ECommandCancelFetch
                                    + TBrCtlDefs::ECommandIdBase);  // send cancel command
}

HBufC* CSwtBrowser::CreateFullUrlLC(const TDesC& aUrl, const TDesC& aUsername,
                                    const TDesC& aPassword)
{
    // username[:password]@server/document
    TInt lPw = aPassword.Length();
    TInt lUn = aUsername.Length();
    _LIT(KBrowserScheme, "://");
    const TInt KBrowserSchemeLength = 3;
    TInt index = aUrl.Find(KBrowserScheme);
    if (index == KErrNotFound)
        index = 0;  // insert at first position
    else
        index += KBrowserSchemeLength;  // insert after scheme

    HBufC *fullUrl = HBufC::NewLC(aUrl.Length() + lUn + lPw + KBrowserSchemeLength);
    fullUrl->Des().Copy(aUrl);
    if (lPw + lUn)
    {
        _LIT(KAt, "@");
        fullUrl->Des().Insert(index, KAt);
    }
    if (lPw)
    {
        _LIT(KColon, ":");
        fullUrl->Des().Insert(index, aPassword);
        fullUrl->Des().Insert(index, KColon);
    }
    if (lUn)
    {
        fullUrl->Des().Insert(index, aUsername);
    }
    fullUrl->Des().ZeroTerminate();
    return fullUrl;
}

TBool CSwtBrowser::IsValidAPFromParamL(TUint32 aIAPid)
{
    CCommsDatabase& db = iActiveApDb->CommsDb();
    CSwtBrowserApUtils* apUtils = CSwtBrowserApUtils::NewL(db);
    CleanupStack::PushL(apUtils);
    TBool retVal = apUtils->WapApExistsL(aIAPid);
    CleanupStack::PopAndDestroy(apUtils);
    return retVal;
}

void CSwtBrowser::UpdateLocalPreferencesL(TPreferencesValues& aValues)
{
    if (iFontSize != aValues.iFontSize)
    {
        iFontSize = aValues.iFontSize;
        iBrCtlInterface->SetBrowserSettingL(
            static_cast < TUint >(TBrCtlDefs::ESettingsFontSize), iFontSize) ;
    }

    if (iTextWrap != aValues.iTextWrap)
    {
        iTextWrap = aValues.iTextWrap;
        iBrCtlInterface->SetBrowserSettingL(
            static_cast < TUint >(TBrCtlDefs::ESettingsTextWrapEnabled), iTextWrap);
    }
    if (iEncoding != aValues.iEncoding)
    {
        iEncoding = aValues.iEncoding;
        iBrCtlInterface->SetBrowserSettingL(
            static_cast < TUint >(TBrCtlDefs::ESettingsCharacterset), iEncoding);
    }
}

void CSwtBrowser::UpdateGlobalPreferencesL(TBrCtlDefs::TBrCtlSettings aSettingType)
{
    // Local Settings should be ignored
    switch (aSettingType)
    {
    case TBrCtlDefs::ESettingsAutoLoadImages:
    {
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsAutoLoadImages, Preferences().AutoLoadImages());
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsDisableFlash, !Preferences().AutoLoadImages());
        break;
    }
    case TBrCtlDefs::ESettingsEmbedded:
    {
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsEmbedded, 0);   // Always disable embeded mode
        break;
    }
    case TBrCtlDefs::ESettingsCookiesEnabled:
    {
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsCookiesEnabled, Preferences().Cookies());
        break;
    }
    case TBrCtlDefs::ESettingsECMAScriptEnabled:
    {
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsECMAScriptEnabled, Preferences().Ecma());
        break;
    }
    case TBrCtlDefs::ESettingsIMEINotifyEnabled:
    {
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsIMEINotifyEnabled, Preferences().IMEINotification());
        break;
    }
    case TBrCtlDefs::ESettingsSendRefererHeader:
    {
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsSendRefererHeader, Preferences().SendReferrer());
        break;
    }
    case TBrCtlDefs::ESettingsSecurityWarnings:
    {
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsSecurityWarnings, Preferences().HttpSecurityWarnings());
        break;
    }

    case TBrCtlDefs::ESettingsPageOverview:
    {
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsPageOverview, Preferences().PageOverview());
        break;
    }
    case TBrCtlDefs::ESettingsBackList:
    {
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsBackList, Preferences().BackList());
        break;
    }
    case TBrCtlDefs::ESettingsAutoRefresh:
    {
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsAutoRefresh, Preferences().AutoRefresh());
        break;
    }

    case TBrCtlDefs::ESettingsAutoFormFillEnabled:
    {
        iBrCtlInterface->SetBrowserSettingL(TBrCtlDefs::ESettingsAutoFormFillEnabled, Preferences().FormDataSaving());
        break;
    }

    // LOCAL SETTINGS should be ignored
    case TBrCtlDefs::ESettingsTextWrapEnabled:
    case TBrCtlDefs::ESettingsFontSize:
    case TBrCtlDefs::ESettingsCharacterset:
    {
        break;
    }

    case TBrCtlDefs::ESettingsUnknown: // ignore
    default:
        break;
    }
}


// ---------------------------------------------------------
// Called by framework when the view size is changed
// ---------------------------------------------------------
//
void CSwtBrowser::SizeChanged()
{
    if (StartedUp())
    {
        CSwtComposite::SizeChanged();
    }

    if (iContainer  && iBrCtlInterface)
    {
        iContainer->SetRect(CalcBrowserRect());
    }
}

// ---------------------------------------------------------
// Called by framework when the view position is changed
// ---------------------------------------------------------
//
void CSwtBrowser::PositionChanged()
{
    CSwtComposite::PositionChanged();
    if (iContainer  && iBrCtlInterface)
    {
        iContainer->SetPosition(CalcBrowserRect().iTl);
    }
}

void CSwtBrowser::FocusChanged(TDrawNow aDrawNow)
{
    if (iContainer && iBrCtlInterface)
    {
        iContainer->SetFocus(IsFocused());
        if (IsFocused())
        {
            TRAP_IGNORE(iBrCtlInterface->HandleCommandL(TBrCtlDefs::ECommandGainFocus +
                        TBrCtlDefs::ECommandIdBase));
        }
        else
        {

            if (iCbaState ==  CSwtBrowser::EActivatedInputBox)
            {
                TRAP_IGNORE(iBrCtlInterface->HandleCommandL(TBrCtlDefs::ECommandAccept +
                            TBrCtlDefs::ECommandIdBase));
            }

            TRAP_IGNORE(iBrCtlInterface->HandleCommandL(
                            TBrCtlDefs::ECommandLoseFocus + TBrCtlDefs::ECommandIdBase));
        }
    }

    CAknControl::FocusChanged(ENoDrawNow);

    if (StartedUp())
    {
        HandleFocusChanged(aDrawNow);
        if (iCbaState ==  CSwtBrowser::EActivatedInputBox)
        {
            iCbaState = CSwtBrowser::EDefault; // force to update cba2
            TRAP_IGNORE(UpdateCbaL());
        }
    }
}

TInt CSwtBrowser::CountComponentControls() const
{
    TInt result = 0;

    // Scroll-bar frame's components
    if (iSbFrame)
    {
        result += iSbFrame->CountComponentControls();
    }
    if (iContainer)   // browser control
    {
        result += 1;
    }
    return result;
}

CCoeControl* CSwtBrowser::ComponentControl(TInt aIndex) const
{
    // Scroll-bar frame's components
    TInt count = 0;
    if (iSbFrame)
    {
        count = iSbFrame->CountComponentControls();
        if (aIndex < count)
        {
            return iSbFrame->ComponentControl(aIndex);
        }
    }

    if (iContainer && aIndex >= count && aIndex < CountComponentControls())
    {
        return iContainer;
    }

    ASSERT(EFalse);
    return NULL;
}

TKeyResponse CSwtBrowser::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
{
    // Well, well, well :) The history view (back view) translates
    // pointer events into EEventKeyUp Select key events. If we
    // detect that the new key event starts with EEventKeyUp and
    // not EEventKeyDown as it should, we assume it is due to the
    // history view trick and therefore we just forward the key
    // to the native browser.
    TKeyResponse res = EKeyWasNotConsumed;
    if (iHandlingPointerEv)
    {
        res = iBrCtlInterface->OfferKeyEventL(aKeyEvent, aType);
    }
    else
    {
        res = HandleKeyL(aKeyEvent, aType, EFalse);
    }
    return res;
}

void CSwtBrowser::ProcessKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
{
    TKeyResponse result(EKeyWasNotConsumed);
    TKeyEvent keyEvent(aKeyEvent);

    // convert Enter key to KeyOk, this is only for emulator
    if (aType == EEventKey &&  keyEvent.iCode == EKeyEnter)
    {
        keyEvent.iCode = EKeyOK;
    }

    if (aType == EEventKey && keyEvent.iCode == EKeyOK)
    {
        if (keyEvent.iRepeats && iSelectionKeyPressed)
        {
            TBrCtlDefs::TBrCtlElementType elementtype =
                iBrCtlInterface->FocusedElementType();
            TInt command(KErrNotFound);
            switch (elementtype)
            {
            case TBrCtlDefs::EElementAnchor:
            {
                command = TBrCtlDefs::ECommandOpen;
                break;
            }
            default:
                break;
            }
            if (command == TBrCtlDefs::ECommandOpen)
            {
                iSelectionKeyPressed = EFalse;
                keyEvent.iCode = EKeyNull;
                result = EKeyWasConsumed;
                iBrCtlInterface->HandleCommandL(
                    command + TBrCtlDefs::ECommandIdBase);
            }
        }
    }

    // Stop the event handling when find item was actived
    if ((keyEvent.iScanCode == EStdKeyDevice3 || keyEvent.iScanCode == EStdKeyXXX)
            && aType == EEventKeyDown)
    {
        iSelectionKeyPressed = ETrue;
        keyEvent.iCode = EKeyNull;
    }

    if (result == EKeyWasNotConsumed)
    {
        result = iBrCtlInterface->OfferKeyEventL(keyEvent, aType);
    }

    if (result == EKeyWasNotConsumed &&
            (keyEvent.iScanCode == EStdKeyDevice3 || keyEvent.iScanCode == EStdKeyXXX) &&
            aType == EEventKeyUp  &&
            iSelectionKeyPressed)
    {
        // Selection key was released and it is not a long press
        iSelectionKeyPressed = EFalse;
        aType = EEventKey;
        keyEvent.iCode = EKeyOK;

        iBrCtlInterface->OfferKeyEventL(keyEvent, aType);
    }
}

void CSwtBrowser::ProcessCommandL(TInt aCmdId)
{
    if (aCmdId-KSwtCommandBaseId == EAknSoftkeyCancel)
    {
        iBrCtlInterface->HandleCommandL(TBrCtlDefs::ECommandCancel + TBrCtlDefs::ECommandIdBase);
    }
    else if (aCmdId-KSwtCommandBaseId == EAknSoftkeyOk)
    {
        if (iCbaState == CSwtBrowser::EActivatedInputBox)
        {
            iBrCtlInterface->HandleCommandL(
                TBrCtlDefs::TBrCtlDefs::ECommandAccept + TBrCtlDefs::ECommandIdBase);
        }
    }
}