webengine/osswebengine/WebKit/s60/plugins/PluginSkin.cpp
branchRCL_3
changeset 94 919f36ff910f
parent 93 79859ed3eea9
child 99 ca6d8a014f4b
--- a/webengine/osswebengine/WebKit/s60/plugins/PluginSkin.cpp	Tue Aug 31 16:17:46 2010 +0300
+++ b/webengine/osswebengine/WebKit/s60/plugins/PluginSkin.cpp	Wed Sep 01 12:28:30 2010 +0100
@@ -16,11 +16,11 @@
 */
 
 //INCLUDES
-#include <Browser_platform_variant.hrh>
+#include <Browser_Platform_Variant.hrh>
 #include "../../bidi.h"
 #include "PlatformString.h"
 #include <centralrepository.h>
-#include <BrowserUiSDKCRKeys.h>
+#include <browseruisdkcrkeys.h>
 #include "PluginSkin.h"
 #include "PluginWin.h"
 #include "PluginHandler.h"
@@ -33,9 +33,9 @@
 #include "BrCtl.h"
 #include "WebCoreGraphicsContext.h"
 #include "StaticObjectsContainer.h"
-#include "BrCtlDefs.h"
+#include <brctldefs.h>
 #include "SettingsContainer.h"
-#include <uri8.h>
+#include <Uri8.h>
 #include <StringLoader.h>
 #include <Webkit.rsg>
 #include "Frame.h"
@@ -43,16 +43,17 @@
 #include "DocumentLoader.h"
 #include "ResourceRequest.h"
 #include "Widget.h"
-#include "PlatformScrollbar.h"
+#include "PlatformScrollBar.h"
+#include "Page.h"
+#include "FocusController.h"
 
 #include <ApEngineConsts.h>
-#include <uri8.h>
-#include <InternetConnectionManager.h>
+#include <Uri8.h>
+#include <internetconnectionmanager.h>
 #include <es_enum.h>
-#include <TextEncoding.h>
-#include "CString.h"
 #include "WidgetExtension.h"
-#include <WidgetRegistryClient.h>
+#include <widgetregistryclient.h>
+
 
 // CONSTANTS
 using namespace WebCore;
@@ -84,8 +85,11 @@
 _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;
@@ -100,10 +104,13 @@
 // return an absolute url that results from refUrl being resolved against 
 // baseUrl.
 // ----------------------------------------------------------------------------
-HBufC8* makeAbsoluteUrlL(const TDesC8& baseUrl, const TDesC8& refUrl)
+HBufC8* makeAbsoluteUrlL(const TDesC8* baseUrl,const TDesC8* docUrl, const TDesC8& refUrl)
 {
     TUriParser8 baseUrlparser;
-    baseUrlparser.Parse(baseUrl); 
+    if(baseUrl == NULL)
+        baseUrlparser.Parse(*docUrl); 
+    else
+        baseUrlparser.Parse(*baseUrl);
     TUriParser8 refUrlparser;
     refUrlparser.Parse(refUrl); 
 
@@ -155,12 +162,13 @@
       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_oldRect(TRect(0,0,0,0)),
-      m_oldViewport(TRect(0,0,0,0))
+      m_resized(false)
   {
   }
 
@@ -194,8 +202,11 @@
 #endif
 
         TInt uid = wdgtExt->GetWidgetId();         
+        
         CWidgetPropertyValue* AccessValue = widgetregistry.GetWidgetPropertyValueL(TUid::Uid(uid), EAllowNetworkAccess ); 
-        TInt networkAccess = *AccessValue;
+        TInt networkAccess = AccessValue && *AccessValue;
+        delete AccessValue;
+        
         const TDesC& allowNetworkAccess = KAllowNetworkAccess();
         NPN_GenericElement NetworkAccess(allowNetworkAccess,networkAccess);
         iGenericElementArray->AppendL(NetworkAccess);
@@ -397,12 +408,37 @@
     delete m_attributeNames; m_attributeNames = 0;
     delete m_attributeValues; m_attributeValues = 0;
     delete m_url; m_url = 0;
-    delete iJavascriptTimer; iJavascriptTimer = 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()
@@ -462,7 +498,9 @@
 
     CFbsBitmap* bitmap = m_cannedimg.m_img;
     TSize bmpSize( bitmap->SizeInPixels() );
-    if ( !m_pluginwin && newRect.Height() >= bmpSize.iHeight && newRect.Width() >= bmpSize.iWidth )
+    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() );
@@ -472,9 +510,35 @@
         }
     if(m_pluginwin)
         {
-        positionChanged();
-        // Force the control to be redrawn.
-        m_pluginwin->refreshPlugin(*gc,newRect);
+        //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);
+            }
         }
     }
 
@@ -502,10 +566,37 @@
 // ----------------------------------------------------------------------------
 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)
+        if(m_active && !visible)
             deActivate();
         m_pluginwin->makeVisible(visible);
         }
@@ -565,6 +656,7 @@
                 {
                 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);
                 }
@@ -650,11 +742,9 @@
         NPError error( NPERR_NO_ERROR );
         
         m_instance = (NPP) User::AllocL(sizeof(NPP_t));
-        m_instance->ndata = pluginWin();
-        m_instance->pdata = NULL;
-
         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 );
@@ -671,9 +761,9 @@
                 }
                 if (m_pluginwin) {
                     m_pluginwin->ConstructL(*(control(m_frame)->webView()));
+                }
             }
         }
-        }
 
         switch ( error ) {
             case NPERR_OUT_OF_MEMORY_ERROR: {
@@ -684,13 +774,11 @@
                 User::Leave( KErrNotSupported );
                 break;
             }
-        }    
+        }
         
         if (m_pluginwin)
-        m_pluginwin->SetExtent( TPoint(0,0), TSize(0,0) );
-            
+            m_pluginwin->SetExtent( TPoint(0,0), TSize(0,0) );
     }
-
 }
 
 // -----------------------------------------------------------------------------
@@ -800,11 +888,11 @@
 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());
@@ -821,24 +909,18 @@
      }
 
     // make sure it is an absolute URL
-    HBufC8* absoluteUrl = makeAbsoluteUrlL(*m_url, 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);
 
-    if (loadmode == ELoadModePlugin ) {    
-        
+    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);
+            NetscapePlugInStreamLoaderClient* pluginloader = NetscapePlugInStreamLoaderClient::NewL(url, this, core(m_frame), notifydata, notify);
             if (pluginloader) {
-                pluginloader->start();                            
-
-                if ( notify ) {
-                    HBufC* url16 = HBufC::NewLC( url.Length() );
-                    url16->Des().Copy( url );
-                    m_pluginfuncs->urlnotify( m_instance, *url16, NPRES_DONE, notifydata );        
-                    CleanupStack::PopAndDestroy(url16);
-                }
-                
+                pluginloader->start();                                          
             }                
         }                 
     }
@@ -849,7 +931,7 @@
         CleanupStack::PopAndDestroy(windowType);
     }
 
-    CleanupStack::PopAndDestroy(absoluteUrl);
+    CleanupStack::PopAndDestroy(2);
 
     return KErrNone;
 }
@@ -857,7 +939,9 @@
 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* absoluteUrl = makeAbsoluteUrlL(*m_url, 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);
  
@@ -907,11 +991,9 @@
         int start_content = buffer.Find(KRequestEOH());    
         start_content =  (start_content != KErrNotFound) ? start_content+ KRequestEOH().Length() : 0;                
         
-        HBufC* body = HBufC::NewLC(buffer.Mid(start_content).Length()+1);                
-        body->Des().Copy(buffer.Mid(start_content));
-        TextEncoding *ecoder = new TextEncoding(core(mainFrame(m_frame))->loader()->encoding());
-        CString decoded_body = ecoder->encode(body->Des().PtrZ(),body->Length());
-        FormData* fd = new (ELeave) FormData(decoded_body.data(),decoded_body.length());                                               
+        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
     }
@@ -920,17 +1002,9 @@
     if (loadmode == ELoadModePlugin ) {    
                         
         if (m_instance && m_pluginfuncs) {
-            NetscapePlugInStreamLoaderClient* pluginloader = NetscapePlugInStreamLoaderClient::NewL(request, this, core(m_frame), notifydata);
+            NetscapePlugInStreamLoaderClient* pluginloader = NetscapePlugInStreamLoaderClient::NewL(request, this, core(m_frame), notifydata, notify);
             if (pluginloader) {
-                pluginloader->start();                            
-
-                if ( notify ) {
-                    HBufC* url16 = HBufC::NewLC( url.Length() );
-                    url16->Des().Copy( url );
-                    m_pluginfuncs->urlnotify( m_instance, *url16, NPRES_DONE, notifydata );        
-                    CleanupStack::PopAndDestroy(url16);
-                }
-                
+                pluginloader->start();                                           
             }                
         }                 
     }
@@ -942,7 +1016,7 @@
     }
     
 
-    CleanupStack::PopAndDestroy(absoluteUrl);
+    CleanupStack::PopAndDestroy(2);
 
     return KErrNone;
 }
@@ -993,15 +1067,32 @@
 
 void* PluginSkin::pluginScriptableObject()
 {
-    //
-    if (m_pluginfuncs && m_pluginfuncs->getvalue) {
-        void *value = 0;
-        NPError npErr = m_pluginfuncs->getvalue( m_instance, NPPVpluginScriptableNPObject, (void *)&value);
-        if (npErr == NPERR_NO_ERROR) {
-            return value;
+    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 (void *)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)
@@ -1011,9 +1102,13 @@
     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 || scheme.CompareF( _L8("data") ) == 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;
 }
@@ -1050,8 +1145,11 @@
                            frameRectInViewCoord.Intersects(viewRect);
       
     if (m_pluginwin) {
-        m_pluginwin->makeVisible( isFrameVisible && !isPageViewMode && isPluginVisible);
-        if (!m_pluginwin->isPluginInFullscreen()) {
+        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);
         }
@@ -1187,3 +1285,151 @@
 
     return EWindowTypeUnknown;
 }
+
+void PluginSkin::reCreatePlugin()
+{
+    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) {
+            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);
+            }
+        }
+
+    }