/*
* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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:
*
*/
//INCLUDES
#include <Browser_Platform_Variant.hrh>
#include "../../bidi.h"
#include "PlatformString.h"
#include <centralrepository.h>
#include <browseruisdkcrkeys.h>
#include "PluginSkin.h"
#include "PluginWin.h"
#include "PluginHandler.h"
#include "PluginStreamLoaderClient.h"
#include "PluginStream.h"
#include "WebFrame.h"
#include "WebFrameView.h"
#include "WebView.h"
#include "WebPageFullScreenHandler.h"
#include "BrCtl.h"
#include "WebCoreGraphicsContext.h"
#include "StaticObjectsContainer.h"
#include <brctldefs.h>
#include "SettingsContainer.h"
#include <Uri8.h>
#include <StringLoader.h>
#include <Webkit.rsg>
#include "Frame.h"
#include "FrameLoader.h"
#include "DocumentLoader.h"
#include "ResourceRequest.h"
#include "Widget.h"
#include "PlatformScrollBar.h"
#include "Page.h"
#include "FocusController.h"
#include <ApEngineConsts.h>
#include <Uri8.h>
#include <internetconnectionmanager.h>
#include <es_enum.h>
#include "WidgetExtension.h"
#include <widgetregistryclient.h>
// CONSTANTS
using namespace WebCore;
// scheme for RTSP url
_LIT8(KRtsp, "rtsp");
_LIT(KAccessPtId, "accesspointid");
_LIT(KContentType, "contenttype");
_LIT(KContentTypeFlash, "flash");
_LIT(KContentTypeUnknown, "application/octet-stream");
_LIT(KRequestContentType, "Content-Type:");
_LIT(KRequestEOF, "\r\n");
_LIT(KRequestEOH, "\r\n\r\n");
// The default placeholder width, matches the value set in html4.css
const TUint KPlaceholderWidth( 100 );
const TUint KPlaceholderHeight( 50 );
// The Padding between object and border, matches the value in html4.css
const TUint KHtml4cssPadding( 1 );
// The border is grow/shrink by this much when the focus changes
const TUint KBorderWidthUnfocus( 0 );
const TUint KBorderWidthFocus( KHtml4cssPadding );
_LIT(KBrowserMode,"BrowserMode");
_LIT(KWidgetMode,"WidgetMode");
_LIT(KUnknownMode, "UnKnownMode");
_LIT(KApplicationId,"ApplicationId");
_LIT(KSecMgrScriptSession,"SecMgrScriptSession");
_LIT(KAllowNetworkAccess,"AllowNetworkAccess");
#if defined(__PLATFORM_VERSION_32__)
#define KArraySize 1
#else
#define KArraySize 3
#endif
const TInt32 KWidgetApplicationId = 0x10282822;
const TInt32 KBrowserApplicationId = 0x10008D39;
//MACROS
//DATATYPES
// LOCAL FUNCTION PROTOTYPES
TInt RunScriptCb( TAny* aPtr );
// ----------------------------------------------------------------------------
// makeAbsoluteUrlL()
// return an absolute url that results from refUrl being resolved against
// baseUrl.
// ----------------------------------------------------------------------------
HBufC8* makeAbsoluteUrlL(const TDesC8* baseUrl,const TDesC8* docUrl, const TDesC8& refUrl)
{
TUriParser8 baseUrlparser;
if(baseUrl == NULL)
baseUrlparser.Parse(*docUrl);
else
baseUrlparser.Parse(*baseUrl);
TUriParser8 refUrlparser;
refUrlparser.Parse(refUrl);
CUri8* absoluteUrl = CUri8::ResolveL(baseUrlparser, refUrlparser);
CleanupStack::PushL(absoluteUrl);
HBufC8* absoluteUrlBuf = HBufC8::NewL(absoluteUrl->Uri().UriDes().Length());
TPtr8 absoluteUrlDes = absoluteUrlBuf->Des();
absoluteUrlDes.Copy(absoluteUrl->Uri().UriDes());
CleanupStack::PopAndDestroy(absoluteUrl);
return absoluteUrlBuf;
}
// ----------------------------------------------------------------------------
// PluginSkin::NewL()
// Two-phased constructor for PluginSkin
// ----------------------------------------------------------------------------
PluginSkin* PluginSkin::NewL( WebFrame& frame,
const TPtrC8& url,
const Vector<WebCore::String>& attributesNames,
const Vector<WebCore::String>& attributeValues,
const TPtrC8& baseUrl,
const WebCore::String& mimeType,
TBool canInteract )
{
PluginSkin* self = NULL;
//Check if the flash plugin is enabled or disabled.
self = new (ELeave) PluginSkin( frame );
CleanupStack::PushL( self );
self->ConstructL( mimeType, attributesNames, attributeValues,
url, baseUrl, canInteract );
CleanupStack::Pop(); // self
return self;
}
// ----------------------------------------------------------------------------
// PluginSkin::PluginSkin()
// Default constructor for PluginSkin
// ----------------------------------------------------------------------------
PluginSkin::PluginSkin( WebFrame& frame )
: m_pluginwin(0),
m_frame( &frame ),
m_visible( EFalse ),
m_pluginSupported( EFalse ),
m_pluginClosed(false),
m_canInteract( EFalse ),
m_rect(TRect(0,0,0,0)),
m_ref(1),
m_oldRect(TRect(0,0,0,0)),
m_oldViewport(TRect(0,0,0,0)),
m_NPObject(0),
m_handle(-1),
m_instance(0),
m_pluginfuncs(0),
m_resized(false),
m_OccReLoad(EFalse)
{
}
void PluginSkin::addWidgetAttributesL()
{
const TDesC& SecMgrScriptSession = KSecMgrScriptSession();
RWidgetRegistryClientSession widgetregistry;
TInt ret = widgetregistry.Connect();
if ( ret != KErrNone && ret != KErrAlreadyExists ) {
User::Leave( ret );
}
else {
CleanupClosePushL( widgetregistry );
}
CBrCtl* brCtl = control(this->frame());
WebView* view = brCtl->webView();
CWidgetExtension* wdgtExt = view->widgetExtension();
if(wdgtExt){
#if defined(BRDO_LIW_FF)
void* scriptSession = wdgtExt->getSecuritySession();
if ( !scriptSession ) {
User::Leave( KErrGeneral );
}
NPN_GenericElement ScriptSession(SecMgrScriptSession,scriptSession);
iGenericElementArray->AppendL(ScriptSession);
#endif
TInt uid = wdgtExt->GetWidgetId();
CWidgetPropertyValue* AccessValue = widgetregistry.GetWidgetPropertyValueL(TUid::Uid(uid), EAllowNetworkAccess );
TInt networkAccess = AccessValue && *AccessValue;
delete AccessValue;
const TDesC& allowNetworkAccess = KAllowNetworkAccess();
NPN_GenericElement NetworkAccess(allowNetworkAccess,networkAccess);
iGenericElementArray->AppendL(NetworkAccess);
}
User::LeaveIfError(widgetregistry.Disconnect());
CleanupStack::PopAndDestroy(); //widgetregistry
}
const TDesC& PluginSkin::GetExecutionMode()
{
TUid uid = RProcess().SecureId();
if( uid.iUid == KWidgetApplicationId ){
return KWidgetMode;
}
else if( uid.iUid == KBrowserApplicationId ){
return KBrowserMode;
}
return KUnknownMode;
}
void PluginSkin::setupGenericElementArrrayL()
{
iGenericElementArray = new (ELeave) RArray<NPN_GenericElement> (KArraySize);
const TDesC& appId = KApplicationId();
const TDesC& executionMode = GetExecutionMode();
NPN_GenericElement ExecutionModeElement(appId,executionMode);
iGenericElementArray->AppendL(ExecutionModeElement);
if(0 == executionMode.Compare(KWidgetMode())) {
addWidgetAttributesL();
}
}
// ----------------------------------------------------------------------------
// PluginSkin::ConstructL()
// Second phase constructor for PluginSkin
// ----------------------------------------------------------------------------
void PluginSkin::ConstructL( const WebCore::String& mimeType,
const Vector<WebCore::String>& attributesNames,
const Vector<WebCore::String>& attributeValues,
const TPtrC8& url,
const TPtrC8& baseUrl,
TBool canInteract )
{
// Get the canned object images
m_cannedimg = WebCore::StaticObjectsContainer::instance()->webCannedImages()->getImage( WebCannedImages::EImageObject );
TInt value( 0 );
CRepository* rep = CRepository::NewL( KCRUidBrowser );
rep->Get( KBrowserUsBuild, value );
delete rep;
if ( !value || canInteract )
{
m_canInteract = ETrue;
}
// Create the plugin if supported by platform
PluginHandler* pluginHandler = WebCore::StaticObjectsContainer::instance()->pluginHandler();
TPtrC mimeTypePtr;
if (mimeType.length() > 0) {
mimeTypePtr.Set(mimeType.des());
m_pluginSupported = pluginHandler->isSupported( mimeTypePtr, url );
}
else {
HBufC* ptr = pluginHandler->pluginMimeByExtention(url);
if (ptr) {
mimeTypePtr.Set(ptr->Des());
}
m_pluginSupported = ((ptr != NULL) && (mimeTypePtr.Length() > 0));
}
if ( m_pluginSupported ) {
m_attributeNames = new (ELeave) CDesCArrayFlat(attributesNames.size());
m_attributeValues = new (ELeave) CDesCArrayFlat(attributeValues.size());
for (TInt i = 0; i < attributesNames.size(); i++)
{ m_attributeNames->AppendL(attributesNames[i].des());}
for (TInt i = 0; i < attributeValues.size(); i++)
{ m_attributeValues->AppendL(attributeValues[i].des());}
m_attributeNames->AppendL( KContentType() );
m_attributeValues->AppendL( mimeType.des());
// Append the browser access point id.
// The access point id could be used by plugins to make open up a connection.
m_attributeNames->AppendL( KAccessPtId );
// Convert int value to string and append it
TBuf16<4> value;
value.Format( _L("%d"), m_frame->frameView()->topView()->accessPointId() );
m_attributeValues->AppendL( value );
setupGenericElementArrrayL();
if(url.Length())
m_url = url.AllocL();
bool loadPluginContent = m_frame->frameView()->topView()->brCtl()->settings()->brctlSetting(TBrCtlDefs::ESettingsAutoLoadImages);
if((mimeTypePtr.Find(KContentTypeFlash) != KErrNotFound)) {
loadPluginContent = loadPluginContent && !m_frame->frameView()->topView()->brCtl()->settings()->brctlSetting(TBrCtlDefs::ESettingsDisableFlash);
m_flashContent = ETrue;
}
else {
m_flashContent = EFalse;
}
if (loadPluginContent) {
if (isBrowserScheme(url)) {
NetscapePlugInStreamLoaderClient* pluginloader = NetscapePlugInStreamLoaderClient::NewL(url, this, core(m_frame));
if (pluginloader) {
pluginloader->start();
}
}
else {
TPtrC8 urlPtr(url);
HBufC8* mime = NULL;
mime = HBufC8::NewLC(mimeTypePtr.Length());
mime->Des().Copy(mimeTypePtr);
createPluginWinL(urlPtr, mimeTypePtr);
loadPluginL(*mime);
CleanupStack::PopAndDestroy(); // mime
}
}
} // end of if (iIsPluginSupported)
else {
if(url.Length())
m_url = url.AllocL();
}
// register itself
MemoryManager::AddCollector(this);
iJavascriptTimer = NULL;
}
void PluginSkin::addPluginStream(PluginStream* stream)
{
m_streams.add(stream);
}
void PluginSkin::removePluginStream(PluginStream* stream)
{
m_streams.remove(stream);
}
// ----------------------------------------------------------------------------
// PluginSkin::~PluginSkin()
// PluginSkin class Destructor
// ----------------------------------------------------------------------------
PluginSkin::~PluginSkin()
{
MemoryManager::RemoveCollector(this);
Close();
RFs& rfs = StaticObjectsContainer::instance()->fsSession();
for(TInt i=0; i < m_tempFilesArray.Count(); i++)
{
rfs.Delete(m_tempFilesArray[i]->Des());
}
m_tempFilesArray.ResetAndDestroy();
if (iGenericElementArray){
iGenericElementArray->Close();
delete iGenericElementArray;
}
}
void PluginSkin::Close()
{
// close any pending stream
Vector<PluginStream*> streams;
for (HashSet<PluginStream*>::iterator it = m_streams.begin(); it != m_streams.end(); ++it) {
streams.append(*it);
}
for (int i=0; i<streams.size(); ++i) {
streams[i]->close();
}
m_streams.clear();
if (m_instance && m_pluginfuncs && m_pluginfuncs->destroy) {
m_pluginfuncs->destroy(m_instance, NULL);
}
if (m_handle >= 0) {
PluginHandler* pluginhandler = WebCore::StaticObjectsContainer::instance()->pluginHandler();
if ( pluginhandler) {
pluginhandler->unloadPlugin( m_handle );
pluginhandler->removePluginObject(this);
if (this == pluginhandler->activePlugin()) {
pluginhandler->setActivePlugin(NULL);
}
}
m_handle = -1;
}
User::Free(m_instance); m_instance = 0;
delete m_pluginwin; m_pluginwin = 0;
delete m_attributeNames; m_attributeNames = 0;
delete m_attributeValues; m_attributeValues = 0;
delete m_url; m_url = 0;
if(iJavascriptTimer)
{
iJavascriptTimer->Cancel();
delete iJavascriptTimer;
iJavascriptTimer = 0;
}
m_pluginfuncs = 0;
m_pluginSupported = EFalse;
m_pluginClosed = true;
}
// ----------------------------------------------------------------------------
// PluginSkin::HandleLosingForeground()
// PluginSkin function to handle Losing foreground event
// ----------------------------------------------------------------------------
void PluginSkin::HandleLosingForeground()
{
if(m_pluginwin)
m_pluginwin->HandleLosingForeground();
}
// ----------------------------------------------------------------------------
// PluginSkin::HandleGainingForeground()
// PluginSkin function to handle Gaining foreground event
// ----------------------------------------------------------------------------
void PluginSkin::HandleGainingForeground()
{
if(m_pluginwin)
m_pluginwin->HandleGainingForeground();
}
// ----------------------------------------------------------------------------
// PluginSkin::pluginFocusChanged()
// PluginSkin function to show/hide fullscreen sprite
// ----------------------------------------------------------------------------
void PluginSkin::pluginFocusChanged(TBool focus)
{
if (control(m_frame)->webView()->pageFullScreenHandler() &&
!control(m_frame)->webView()->pageFullScreenHandler()->isFullScreenMode())
return;
if (focus && !m_flashContent)
{
TRAP_IGNORE(
control(m_frame)->webView()->LeaveFullscreenBrowsingL();
control(m_frame)->webView()->notifyFullscreenModeChangeL( EFalse );
);
}
else if (focus)
{
TRAP_IGNORE(
control(m_frame)->webView()->pageFullScreenHandler()->showEscBtnL();
);
}
else
{
TRAP_IGNORE(
control(m_frame)->webView()->pageFullScreenHandler()->hideEscBtnL();
);
}
}
// ----------------------------------------------------------------------------
// PluginSkin::Draw
// From MWebCoreObjectWidget
//
// The "focus" border width of this widget is adjusted to show when it has
// focus. The border width is grown to KBorderWidthFocus. The default padding
// (set in Html4.css) is set up to handle the focus border growing into it.
// ----------------------------------------------------------------------------
void PluginSkin::draw( WebCoreGraphicsContext& context,
const TRect& /*rect*/ )
{
if(!control(m_frame)->webView()->IsVisible())
return;
TRect newRect(m_rect);
TInt z(context.view().scalingFactor());
if (z != 100 )
{
newRect = m_frame->frameView()->toViewCoords(m_rect);
}
CFbsBitGc* gc = &context.gc();
gc->SetPenStyle( CGraphicsContext::ENullPen );
gc->SetBrushStyle( CGraphicsContext::ENullBrush );
CFbsBitmap* bitmap = m_cannedimg.m_img;
TSize bmpSize( bitmap->SizeInPixels() );
CWidgetExtension* wdgtExt = control(this->frame()) ? control(this->frame())->getWidgetExt(): NULL;
if ( !wdgtExt && !m_pluginwin && newRect.Height() >= bmpSize.iHeight && newRect.Width() >= bmpSize.iWidth )
{
// The inner rect is big enough, draw the placeholder image
TPoint bitmapStartPoint( newRect.Center() );
bitmapStartPoint -= TPoint(bmpSize.iWidth/2,bmpSize.iHeight/2);
gc->BitBltMasked( bitmapStartPoint, m_cannedimg.m_img,
bmpSize, m_cannedimg.m_msk, ETrue );
}
if(m_pluginwin)
{
//if bitmap is shared from plugins then draw the shared bitmap
if(m_pluginwin->IsPluginBitMapSet())
{
CFbsBitmap* bitmap = m_pluginwin->PluginBitmap();
if(bitmap)
{
TRect clippingRect = context.clippingRect();
TRect oldcontextrect = context.clippingRect();
if(newRect != clippingRect)
{
context.setClippingRect(newRect);
}
gc->DrawBitmap(newRect, bitmap);
context.setClippingRect(oldcontextrect);
}
else
{
//if not a valid bitmap, then hide that plugin
m_pluginwin->MakeVisible(EFalse);
}
positionChanged();
}
else
{
positionChanged();
// Force the control to be redrawn, for window less plugins
m_pluginwin->refreshPlugin(*gc,newRect);
}
}
}
// ----------------------------------------------------------------------------
// PluginSkin::IsVisible
// From MWebCoreObjectWidget
// ----------------------------------------------------------------------------
TBool PluginSkin::isVisible() const
{
return m_visible;
}
// ----------------------------------------------------------------------------
// PluginSkin::SizeHint
// From MWebCoreObjectWidget
// ----------------------------------------------------------------------------
TSize PluginSkin::sizeHint() const
{
return TSize( KPlaceholderWidth, KPlaceholderHeight );
}
// ----------------------------------------------------------------------------
// PluginSkin::MakeVisible
// From MWebCoreObjectWidget
// ----------------------------------------------------------------------------
void PluginSkin::makeVisible( TBool visible )
{
// if visible is true for a plugin, make sure that the plugin is actually visible in the window before proceeding
TBool visibility = EFalse;
if (visible) {
TRect fullRect(getPluginWinRect());
TRect clipRect(getClipRect());
TRect frameRect(m_frame->frameView()->rect());
TRect viewRect = control(m_frame)->webView()->Rect();
TBool isPageViewMode = control(m_frame)->webView()->inPageViewMode();
WebFrame* pf = m_frame;
TPoint p = frameRect.iTl;
if (m_frame->parentFrame()) {
pf = m_frame->parentFrame();
p = pf->frameView()->frameCoordsInViewCoords(frameRect.iTl);
}
TSize sz = pf->frameView()->toViewCoords(frameRect.Size());
TRect frameRectInViewCoord = TRect(p, sz);
TBool isPluginVisible = frameRectInViewCoord.Intersects(fullRect);
TBool isFrameVisible = m_frame->frameView()->isVisible() &&
frameRectInViewCoord.Intersects(viewRect);
visibility = isFrameVisible && !isPageViewMode && isPluginVisible;
}
if ( m_pluginwin )
{
if (visible && !visibility)
visible = EFalse;
m_visible = visible;
if(m_active && !visible)
deActivate();
m_pluginwin->makeVisible(visible);
}
}
// ----------------------------------------------------------------------------
// PluginSkin::SetFocus
// From MWebCoreObjectWidget
// ----------------------------------------------------------------------------
void PluginSkin::setFocus( TBool focus )
{
m_focused = focus;
}
// ----------------------------------------------------------------------------
// PluginSkin::deActivate
// Invoked when the user selects the control
// ----------------------------------------------------------------------------
void PluginSkin::deActivate()
{
TBool consumed(EFalse);
if (m_pluginwin )
{
TRAP_IGNORE( m_pluginwin->processEventL(EEventDeactivate, consumed));
}
if (consumed)
{
m_active = EFalse;
m_frame->frameView()->topView()->setFocusedElementType(TBrCtlDefs::EElementObjectBox);
// Set right soft key
m_frame->frameView()->topView()->brCtl()->updateDefaultSoftkeys();
}
PluginHandler* pluginHandler = WebCore::StaticObjectsContainer::instance()->pluginHandler();
pluginHandler->setPluginToActivate(NULL);
pluginHandler->setActivePlugin(NULL);
}
// ----------------------------------------------------------------------------
// PluginSkin::activate
// From MWebCoreObjectWidget
// Invoked when the user selects the right key (Cancel)
// ----------------------------------------------------------------------------
void PluginSkin::activate()
{
if (m_pluginClosed)
return;
PluginHandler* pluginHandler = WebCore::StaticObjectsContainer::instance()->pluginHandler();
TBool consumed(EFalse);
if(m_pluginwin)
{
if(m_canInteract)
{
TRAP_IGNORE( m_pluginwin->processEventL(EEventActivate, consumed));
if (consumed)
{
m_active = ETrue;
m_frame->frameView()->topView()->setFocusedElementType(TBrCtlDefs::EElementActivatedObjectBox);
control(m_frame)->webView()->page()->focusController()->setFocusedNode(getElement(), control(m_frame)->webView()->page()->focusController()->focusedOrMainFrame());
pluginHandler->setActivePlugin(this);
pluginHandler->setPluginToActivate(NULL);
}
// Set right soft key
m_frame->frameView()->topView()->brCtl()->updateDefaultSoftkeys();
}
else
{
m_active = ETrue;
pluginHandler->setActivePlugin(this);
TRAP_IGNORE( m_frame->frameView()->topView()->openPluginPlayerL(m_pluginwin));
consumed = ETrue;
m_active = EFalse;
pluginHandler->setActivePlugin(NULL);
}
} else {
if ( m_pluginSupported ) {
NetscapePlugInStreamLoaderClient* pluginloader = NULL;
TRAP_IGNORE( pluginloader = NetscapePlugInStreamLoaderClient::NewL(*m_url, this, core(m_frame)));
if (pluginloader) {
pluginloader->start();
}
}
else {
if (m_url) {
// let the download manager handle this. non-native top level load
mainFrame(m_frame)->loadURL(*m_url, TBrCtlDefs::ECacheModeNoCache, String());
}
}
}
}
// ----------------------------------------------------------------------------
// PluginSkin::Rect
// From MWebCoreObjectWidget
// ----------------------------------------------------------------------------
TRect PluginSkin::rect() const
{
return m_rect;
}
// ----------------------------------------------------------------------------
// PluginSkin::SetRect
// From MWebCoreObjectWidget
// ----------------------------------------------------------------------------
void PluginSkin::setRect(const TRect& rect)
{
m_rect = rect;
}
// ----------------------------------------------------------------------------
// PluginSkin::SetFont
// From MWebCoreObjectWidget
// ----------------------------------------------------------------------------
void PluginSkin::setFont(CFont* font)
{
// Use the font set by our widget, when graphicsContext.UseFont() is called
// the previous font is cleaned up.
m_font = font;
}
// -----------------------------------------------------------------------------
// PluginSkin::IsFocusable
//
// -----------------------------------------------------------------------------
//
TBool PluginSkin::isFocusable() const
{
return ETrue;
}
// -----------------------------------------------------------------------------
// PluginSkin::loadPlugin
//
// Load the plugin.
// -----------------------------------------------------------------------------
void PluginSkin::loadPluginL( const TDesC8& mimetype )
{
if (!m_instance) {
NPError error( NPERR_NO_ERROR );
m_instance = (NPP) User::AllocL(sizeof(NPP_t));
if (m_instance) {
m_instance->ndata = pluginWin();
m_instance->pdata = NULL;
PluginHandler* pluginhandler = WebCore::StaticObjectsContainer::instance()->pluginHandler();
if ( pluginhandler ) {
pluginhandler->loadPluginL( m_handle, &m_pluginfuncs );
if (m_pluginfuncs && m_pluginfuncs->newp) {
error = m_pluginfuncs->newp( TPtrC8(mimetype),
m_instance,
NP_EMBED,
m_attributeNames,
m_attributeValues,
NULL );
}
if (m_pluginwin) {
m_pluginwin->ConstructL(*(control(m_frame)->webView()));
}
}
}
switch ( error ) {
case NPERR_OUT_OF_MEMORY_ERROR: {
User::Leave( KErrNoMemory );
break;
}
case NPERR_GENERIC_ERROR: {
User::Leave( KErrNotSupported );
break;
}
}
if (m_pluginwin) {
m_pluginwin->SetExtent( TPoint(0,0), TSize(0,0) );
if (m_OccReLoad) {
setPluginWinClipedRect();
m_OccReLoad = EFalse;
}
}
}
}
// -----------------------------------------------------------------------------
// PluginSkin::CreatePluginWinL
//
// Initializes a new PluginWin
// -----------------------------------------------------------------------------
//
void PluginSkin::createPluginWinL(TDesC8& url, TDesC& mimetype)
{
if (m_pluginwin)
return;
// The aLoadMode is not currently used. It would be used for checking the
// load mode and determining if the plugin should be deleted and recreated.
// Get plugin handler, so we can find a plugin handle for a plugin that
// supports the incoming content (by mimetype or extension)
PluginHandler* pluginHandler = WebCore::StaticObjectsContainer::instance()->pluginHandler();
m_handle = pluginHandler->findPlugin( mimetype );
if ( m_handle == KErrNotFound ) {
TUriParser8 parser;
if ( parser.Parse(url) == KErrNone ) {
m_handle = pluginHandler->findPluginByExtension( parser.Extract(EUriPath ) );
}
}
if (m_handle == KErrNotFound)
User::Leave(KErrNotSupported);
//Set the cliprect to plugwin
TRect clipRect = TRect(m_rect.iTl, m_frame->frameView()->toDocCoords(m_rect.Size()));
clipRect.Intersection(m_rect);
setClipRect(clipRect);
// Create the PluginWin, if it doesn't exist,
m_pluginSupported = true;
m_pluginwin = PluginWin::NewL(this, *m_frame->frameView()->topView());
pluginHandler->storePluginObject(this);
m_frame->frameView()->invalidateRect(m_rect, EFalse);
}
// -----------------------------------------------------------------------------
// PluginSkin::PositionChanged
// From MViewFocusObserver
// Callback from the view when the position changes
// -----------------------------------------------------------------------------
void PluginSkin::positionChanged()
{
// If the plugin content hasnt arrived yet or plugin is invalid, then return immediately
if ( !m_pluginwin ) {
return;
}
TPoint tl = m_frame->frameView()->frameCoordsInViewCoords(m_rect.iTl);
TPoint br = m_frame->frameView()->frameCoordsInViewCoords(m_rect.iBr);
TRect rect = TRect(tl, br);
TRect newViewport = m_frame->frameView()->topView()->DocumentViewport();
if (m_oldRect != rect || m_oldViewport != newViewport) {
m_oldRect = rect;
m_oldViewport = newViewport;
TRect clipRect(frameVisibleRect());
clipRect.Intersection(m_rect);
setClipRect(clipRect);
setPluginWinClipedRect();
}
}
//-------------------------------------------------------------------------------
// RunScriptCb
// C-style TCallback function
//-------------------------------------------------------------------------------
TInt RunScriptCb(TAny* aPtr )
{
static_cast<PluginSkin*>(aPtr)->RunScript();
return EFalse;
}
// -----------------------------------------------------------------------------
// PluginSkin::forceRedraw
//
//
// -----------------------------------------------------------------------------
void PluginSkin::forceRedraw(bool drawNow)
{
if (m_frame && m_frame->frameView())
m_frame->frameView()->invalidateRect(m_rect, drawNow);
}
// -----------------------------------------------------------------------------
// PluginSkin::RunScript
//
// Runs java script, possibly asynchronously
// -----------------------------------------------------------------------------
//
TBool PluginSkin::RunScript()
{
_LIT8(KJs, "javascript:");
for(int i=0;i<m_JSUrls.Count();i++) {
TPtr16 temp = ((HBufC*)m_JSUrls[i])->Des();
core(mainFrame(m_frame))->loader()->executeScript(String(temp.Mid(KJs().Length())));
}
m_JSUrls.ResetAndDestroy();
return EFalse;
}
//callbacks from NpnImplementation
int PluginSkin::getRequestL(const TDesC8& url, bool notify, void* notifydata,const TDesC* aWindowType)
{
TPluginLoadMode loadmode = GetLoadMode(aWindowType);
if (url.Ptr() == NULL ) {
return KErrArgument;
}
_LIT8(KJs, "javascript:");
if ((url.Length() > KJs().Length() ) &&(url.Left(KJs().Length()).FindF(KJs) == 0)) {
HBufC* pBuffer = HBufC::NewL(url.Length());
TPtr16 temp = pBuffer->Des();
temp.Copy(url);
m_JSUrls.Append(pBuffer);
if(!iJavascriptTimer){
iJavascriptTimer = CIdle::NewL(CActive::EPriorityLow);
}
if( iJavascriptTimer && !iJavascriptTimer->IsActive() ){
iJavascriptTimer->Start(TCallBack(&RunScriptCb, this));
}
return KErrNone;
}
// make sure it is an absolute URL
HBufC8* docUrl = HBufC8::NewLC(core(m_frame)->document()->baseURI().length());
docUrl->Des().Copy(core(m_frame)->document()->baseURI());
HBufC8* absoluteUrl = makeAbsoluteUrlL(m_url, docUrl, url);
CleanupStack::PushL(absoluteUrl);
PluginHandler* pluginHandler = StaticObjectsContainer::instance()->pluginHandler();
if( (loadmode == ELoadModePlugin ) || (loadmode == ELoadModeTop && (pluginHandler->pluginMimeByExtention(url) != NULL)) ){
if (m_instance && m_pluginfuncs) {
NetscapePlugInStreamLoaderClient* pluginloader = NetscapePlugInStreamLoaderClient::NewL(url, this, core(m_frame), notifydata, notify);
if (pluginloader) {
pluginloader->start();
}
}
}
else {
HBufC* windowType = HBufC::NewLC(aWindowType->Length());
windowType->Des().Copy(*aWindowType);
frame()->loadURL(*absoluteUrl,TBrCtlDefs::ECacheModeNormal,String(),&String(*windowType));
CleanupStack::PopAndDestroy(windowType);
}
CleanupStack::PopAndDestroy(2);
return KErrNone;
}
int PluginSkin::postRequestL(const TDesC8& url,const TDesC& buffer, bool fromfile, bool notify, void* notifydata,const TDesC* aWindowType)
{
// make sure it is an absolute URL
HBufC8* docUrl = HBufC8::NewLC(core(m_frame)->document()->baseURI().length());
docUrl->Des().Copy(core(m_frame)->document()->baseURI());
HBufC8* absoluteUrl = makeAbsoluteUrlL(m_url, docUrl, url);
CleanupStack::PushL(absoluteUrl);
TPluginLoadMode loadmode = GetLoadMode(aWindowType);
ResourceRequest request = (KURL(*absoluteUrl));
request.setMainLoad(true);
request.setCachePolicy(UseProtocolCachePolicy);
request.setHTTPMethod("POST");
int contenttype_pos = buffer.Find(KRequestContentType());
if (contenttype_pos != KErrNotFound) {
contenttype_pos += KRequestContentType().Length();
int contenttype_length = buffer.Mid(contenttype_pos).Find(KRequestEOF());
if (contenttype_length != KErrNotFound) {
request.setHTTPContentType(buffer.Mid(contenttype_pos,contenttype_length));
} else {
request.setHTTPContentType(KContentTypeUnknown());
}
} else {
request.setHTTPContentType(KContentTypeUnknown());
}
if ( fromfile ) {
RFs& rfs = StaticObjectsContainer::instance()->fsSession();
RFile file;
User::LeaveIfError(file.Open( rfs, buffer, EFileRead));
CleanupClosePushL(file);
// Get the file size and allocate a buffer
TInt size(0);
User::LeaveIfError( file.Size(size) );
HBufC8* body = HBufC8::NewLC(size);
TPtr8 tptr8(body->Des());
User::LeaveIfError(file.Read(tptr8));
FormData* fd = new (ELeave) FormData(body->Ptr(),body->Length());
request.setHTTPBody(fd);
CleanupStack::PopAndDestroy(2); // file, body
}
else{
int start_content = buffer.Find(KRequestEOH());
start_content = (start_content != KErrNotFound) ? start_content+ KRequestEOH().Length() : 0;
HBufC8* body = HBufC8::NewLC(buffer.Mid(start_content).Length());
body->Des().Copy(buffer.Mid(start_content));
FormData* fd = new (ELeave) FormData(body->Ptr(),body->Length());
request.setHTTPBody(fd);
CleanupStack::PopAndDestroy(); // body
}
if (loadmode == ELoadModePlugin ) {
if (m_instance && m_pluginfuncs) {
NetscapePlugInStreamLoaderClient* pluginloader = NetscapePlugInStreamLoaderClient::NewL(request, this, core(m_frame), notifydata, notify);
if (pluginloader) {
pluginloader->start();
}
}
}
else {
HBufC* windowType = HBufC::NewLC(aWindowType->Length());
windowType->Des().Copy(*aWindowType);
frame()->loadRequest(request,&String(*windowType));
CleanupStack::PopAndDestroy(windowType);
}
CleanupStack::PopAndDestroy(2);
return KErrNone;
}
bool PluginSkin::isInteractive()
{
if (m_instance && m_pluginfuncs) {
bool isNotInteractive = false;
NPError err = m_pluginfuncs->getvalue(m_instance, NPPVpluginInteractiveBool, &isNotInteractive);
if( err == NPERR_NO_ERROR) {
return !isNotInteractive;
}
}
return false;
}
void PluginSkin::openInViewerL()
{
if(m_pluginwin)
{
m_frame->frameView()->topView()->mainFrame()->loadURL(*m_url, TBrCtlDefs::ECacheModeNormal, String());
}
}
/*
// -----------------------------------------------------------------------------
// PluginSkin::HandlePluginError
//
// handles error conditions
// -----------------------------------------------------------------------------
//
void PluginSkin::handlePluginError( TInt error )
{
if ( error != KErrNone )
{
m_pluginSupported = EFalse;
delete m_pluginwin;
m_pluginwin = 0;
}
}
*/
void* PluginSkin::pluginScriptableObject()
{
if (!m_NPObject && m_pluginfuncs && m_pluginfuncs->getvalue) {
NPError npErr = m_pluginfuncs->getvalue( m_instance, NPPVpluginScriptableNPObject, &m_NPObject);
if (npErr != NPERR_NO_ERROR) {
m_NPObject = 0;
}
}
return m_NPObject;
}
TBool validateDataScheme(const TPtrC8& url)
{
// Check if body part of "data:" exists = data:[<mediatype>][;base64],<body>. RFC-2397 : http://www.faqs.org/rfcs/rfc2397
TPtrC8 urlPtr8 = url;
if(url.Length() <= 0 )
return EFalse;
TInt commaPos( urlPtr8.Locate( ',' ) );
if (commaPos == KErrNotFound )
return EFalse;
TPtrC8 datapart (urlPtr8.Mid(commaPos + 1));
if (datapart.Length() <= 0)
return EFalse;
return ETrue;
}
TBool PluginSkin::isBrowserScheme(const TPtrC8& url)
{
TBool supported(EFalse);
TUriParser8 parser;
if( parser.Parse( url ) == KErrNone ) {
TPtrC8 scheme = parser.Extract( EUriScheme );
if (scheme.CompareF( _L8("http" ) ) == 0 || scheme.CompareF( _L8("https" ) ) == 0
|| scheme.Length() == 1 || scheme.CompareF( _L8("file") ) == 0) {
supported = ETrue;
}
else if(scheme.CompareF( _L8("data") ) == 0) {
// if the scheme is "data", check its validity according to RFC-2397 : http://www.faqs.org/rfcs/rfc2397
supported = validateDataScheme(url);
}
}
return supported;
}
void PluginSkin::resized()
{
m_resized = true;
m_frame->frameView()->topView()->forceLayoutAndResize(m_frame);
}
void PluginSkin::setClipRect(TRect rect)
{
m_pluginWinClipRect = rect;
}
void PluginSkin::setPluginWinClipedRect()
{
TRect fullRect(getPluginWinRect());
TRect clipRect(getClipRect());
TRect frameRect(m_frame->frameView()->rect());
TRect viewRect = control(m_frame)->webView()->Rect();
TBool isPageViewMode = control(m_frame)->webView()->inPageViewMode();
WebFrame* pf = m_frame;
TPoint p = frameRect.iTl;
if (m_frame->parentFrame()) {
pf = m_frame->parentFrame();
p = pf->frameView()->frameCoordsInViewCoords(frameRect.iTl);
}
TSize sz = pf->frameView()->toViewCoords(frameRect.Size());
TRect frameRectInViewCoord = TRect(p, sz);
TBool isPluginVisible = frameRectInViewCoord.Intersects(fullRect);
TBool isFrameVisible = m_frame->frameView()->isVisible() &&
frameRectInViewCoord.Intersects(viewRect);
if (m_pluginwin) {
TBool visibility = isFrameVisible && !isPageViewMode && isPluginVisible;
if(fullRect.Size() != TSize(0,0)) {
m_pluginwin->makeVisible(visibility);
}
if (!m_pluginwin->isPluginInFullscreen() && visibility) {
clipRect.Intersection(fullRect);
m_pluginwin->SetRect(clipRect);
}
}
}
TRect PluginSkin::getClipRect() const
{
TPoint pt = m_frame->frameView()->convertContentToView(m_pluginWinClipRect.iTl);
TRect clipRect(pt, m_frame->frameView()->toViewCoords(m_pluginWinClipRect.Size()));
clipRect.Intersection(control(m_frame)->webView()->Rect());
return clipRect;
}
TRect PluginSkin::getPluginWinRect() const
{
TPoint pt = m_frame->frameView()->convertContentToView(m_rect.iTl);
TRect rect(pt, m_frame->frameView()->toViewCoords(m_rect.Size()));
return rect;
}
TRect PluginSkin::frameVisibleRect() const
{
TRect rect = m_frame->frameView()->visibleRect();
if (m_frame->isIframe()) {
if (m_frame->frameView()->vScrollbar() && m_frame->frameView()->vScrollbar()->isEnabled()) {
rect.SetWidth(rect.Width() - m_frame->frameView()->vScrollbar()->width());
}
if (m_frame->frameView()->hScrollbar() && m_frame->frameView()->hScrollbar()->isEnabled()) {
rect.SetHeight(rect.Height() - m_frame->frameView()->hScrollbar()->height());
}
}
return rect;
}
TUint PluginSkin::Collect(TUint aRequired)
{
// out of memory, we need to remove the plugin win and all streams associating with it.
Close();
return 0;
}
TInt PluginSkin::handleNetworkAccess() const
{
TInt conn = 0,sockHandle = 0;
TBool connNeeded;
TApBearerType type;
TInt apId = -1;
TRAP_IGNORE(m_frame->frameView()->topView()->brCtl()->brCtlSpecialLoadObserver()->NetworkConnectionNeededL(&conn,&sockHandle,&connNeeded,&type));
if ( conn )
{
RConnection* connPtr = REINTERPRET_CAST( RConnection*, conn );
TConnectionInfoBuf connInfoBuf;
TUint conns( 0 );
connPtr->EnumerateConnections( conns );
if ( conns > 0 && connPtr->GetConnectionInfo(1, connInfoBuf) == KErrNone )
{
// set the access point id
apId = connInfoBuf().iIapId;
}
}
return apId;
}
TPluginLoadMode PluginSkin::GetLoadMode(const TDesC* aWindowType)
{
TWindowType windowType = GetWindowType(aWindowType);
switch (windowType) {
case EWindowTypePlugin: // Return the load response to the plugin
return ELoadModePlugin;
case EWindowTypeBlank: // New window is opened.
case EWindowTypeNew:
return ELoadModeNew;
case EWindowTypeCurrent: // Replace the plugin with a new document
case EWindowTypeSelf:
return ELoadModeSelf;
case EWindowTypeParent: // Replace the page with a new top level document
return ELoadModeParent;
case EWindowTypeTop:
return ELoadModeTop;
default:
return ELoadModeNone;
}
}
TWindowType PluginSkin::GetWindowType(const TDesC* aWindowType)
{
if ((aWindowType == NULL) ||
(aWindowType->Ptr() == NULL) ||
(aWindowType->Length() == 0)) {
return EWindowTypePlugin;
}
TPtrC windowTypePtr(*aWindowType);
if (windowTypePtr.FindF(KBlank) == 0) {
return EWindowTypeBlank;
}
if (windowTypePtr.FindF(KNew) == 0) {
return EWindowTypeNew;
}
if (windowTypePtr.FindF(KSelf) == 0) {
return EWindowTypeSelf;
}
if (windowTypePtr.FindF(KCurrent) == 0) {
return EWindowTypeCurrent;
}
if (windowTypePtr.FindF(KParent) == 0) {
return EWindowTypeParent;
}
if (windowTypePtr.FindF(KTop) == 0) {
return EWindowTypeTop;
}
return EWindowTypeUnknown;
}
void PluginSkin::reCreatePlugin()
{
TBool visible = EFalse;
if (m_pluginwin && m_pluginwin->IsVisible())
visible = ETrue;
TBuf16<4> apId;
apId.Format( _L("%d"), m_frame->frameView()->topView()->accessPointId() );
if (m_pluginwin ) {
m_pluginwin->notifyAPChange((void*)&apId);
}
if (m_streams.size() > 0) {
//destroy the plugin
Vector<PluginStream*> streams;
for (HashSet<PluginStream*>::iterator it = m_streams.begin(); it != m_streams.end(); ++it) {
streams.append(*it);
}
for (int i=0; i<streams.size(); ++i) {
streams[i]->close();
}
m_streams.clear();
if (m_instance && m_pluginfuncs && m_pluginfuncs->destroy) {
m_pluginfuncs->destroy(m_instance, NULL);
}
User::Free(m_instance); m_instance = 0;
delete m_pluginwin; m_pluginwin = 0;
delete iJavascriptTimer; iJavascriptTimer = 0;
RFs& rfs = StaticObjectsContainer::instance()->fsSession();
for(TInt i=0; i < m_tempFilesArray.Count(); i++) {
rfs.Delete(m_tempFilesArray[i]->Des());
}
m_tempFilesArray.ResetAndDestroy();
//create/load the destroyed plugin again
NetscapePlugInStreamLoaderClient* pluginloader = NetscapePlugInStreamLoaderClient::NewL(m_url->Des(), this, core(m_frame));
if (pluginloader) {
if (visible) {
m_OccReLoad = ETrue;
}
pluginloader->start();
}
}
}
// -----------------------------------------------------------------------------
// PluginWin::NotifyPluginsForScrollOrPinch
// When ever there is Scroll or Pinch zoom is in progress, the webframe will
// Notify all the plugins "ETrue" for Start and "EFalse" for end
// -----------------------------------------------------------------------------
void PluginSkin::NotifyPluginsForScrollOrPinch(bool status)
{
if(m_pluginwin)
{
//while pinch zoom, deactivate and activate the plugins.
WebView* view = control(frame())->webView();
if(!view)
return;
//check weather the collect bitmap is supported or not
TBool bitmapSupported = m_pluginwin->IsCollectBitmapSupported();
//if bitmap is not supported, check for pinch zoom and deactivate the plugins.
if((view->isPinchZoom()))
{
//if bitmap sharing is not supported then deactivate or activate the plugins
if(!bitmapSupported)
{
if(status)
{
if(m_pluginwin->IsVisible())
{
m_pluginwin->MakeVisible(false);
m_pluginwin->setPluginFocusL(false);
}
}
else
{
activate();
}
}
}
if(bitmapSupported)
{
m_pluginwin->GetBitmapFromPlugin(status);
if(!status)
{
m_pluginwin->ClearPluginBitmap();
activateVisiblePlugins();
}
}
}
}
// -----------------------------------------------------------------------------
// PluginWin::IsCollectBitmapSupported
// Check Plugin are supported for Bitmap Sharing
// -----------------------------------------------------------------------------
TBool PluginSkin::IsCollectBitmapSupported()
{
if(m_pluginwin)
{
return m_pluginwin->IsCollectBitmapSupported();
}
return false;
}
void PluginSkin::activateVisiblePlugins()
{
TRect fullRect(getPluginWinRect());
TRect clipRect(getClipRect());
TRect frameRect(m_frame->frameView()->rect());
TRect viewRect = control(m_frame)->webView()->Rect();
TBool isPageViewMode = control(m_frame)->webView()->inPageViewMode();
WebFrame* pf = m_frame;
TPoint p = frameRect.iTl;
if (m_frame->parentFrame())
{
pf = m_frame->parentFrame();
p = pf->frameView()->frameCoordsInViewCoords(frameRect.iTl);
}
TSize sz = pf->frameView()->toViewCoords(frameRect.Size());
TRect frameRectInViewCoord = TRect(p, sz);
TBool isPluginVisible = frameRectInViewCoord.Intersects(fullRect);
TBool isFrameVisible = m_frame->frameView()->isVisible() &&
frameRectInViewCoord.Intersects(viewRect);
TBool visibility = isFrameVisible && !isPageViewMode && isPluginVisible;
if(fullRect.Size() != TSize(0,0))
{
if (visibility)
{
m_pluginwin->MakeVisible(true); //forcefully make the plugin visible, this is for pinch exit
m_pluginwin->makeVisible(true);
}
else
{
//this is required for flash plugin to clear the EGL surface
//when the plugin window is outside the view port
m_pluginwin->makeVisible(false);
}
}
}