src/3rdparty/webkit/WebCore/plugins/PluginView.cpp
changeset 30 5dc02b23752f
parent 3 41300fa6a67c
--- a/src/3rdparty/webkit/WebCore/plugins/PluginView.cpp	Wed Jun 23 19:07:03 2010 +0300
+++ b/src/3rdparty/webkit/WebCore/plugins/PluginView.cpp	Tue Jul 06 15:10:48 2010 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Collabora Ltd. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,48 +27,50 @@
 #include "config.h"
 #include "PluginView.h"
 
+#include "Bridge.h"
+#include "Chrome.h"
 #include "Document.h"
 #include "DocumentLoader.h"
 #include "Element.h"
+#include "FocusController.h"
+#include "Frame.h"
 #include "FrameLoader.h"
+#include "FrameLoaderClient.h"
 #include "FrameTree.h"
-#include "Frame.h"
 #include "FrameView.h"
 #include "GraphicsContext.h"
-#include "Image.h"
 #include "HTMLNames.h"
 #include "HTMLPlugInElement.h"
+#include "Image.h"
+#include "JSDOMBinding.h"
 #include "JSDOMWindow.h"
 #include "KeyboardEvent.h"
 #include "MIMETypeRegistry.h"
 #include "MouseEvent.h"
 #include "NotImplemented.h"
 #include "Page.h"
-#include "FocusController.h"
 #include "PlatformMouseEvent.h"
-#if PLATFORM(WIN_OS) && !PLATFORM(WX) && ENABLE(NETSCAPE_PLUGIN_API)
-#include "PluginMessageThrottlerWin.h"
-#endif
-#include "PluginPackage.h"
-#include "JSDOMBinding.h"
-#include "ScriptController.h"
-#include "ScriptValue.h"
-#include "SecurityOrigin.h"
 #include "PluginDatabase.h"
 #include "PluginDebug.h"
 #include "PluginMainThreadScheduler.h"
 #include "PluginPackage.h"
 #include "RenderBox.h"
 #include "RenderObject.h"
+#include "ScriptController.h"
+#include "ScriptValue.h"
+#include "SecurityOrigin.h"
+#include "Settings.h"
 #include "c_instance.h"
 #include "npruntime_impl.h"
 #include "runtime_root.h"
-#include "Settings.h"
-#include "runtime.h"
 #include <runtime/JSLock.h>
 #include <runtime/JSValue.h>
 #include <wtf/ASCIICType.h>
 
+#if OS(WINDOWS) && ENABLE(NETSCAPE_PLUGIN_API)
+#include "PluginMessageThrottlerWin.h"
+#endif
+
 using JSC::ExecState;
 using JSC::JSLock;
 using JSC::JSObject;
@@ -85,6 +87,14 @@
 
 static int s_callingPlugin;
 
+typedef HashMap<NPP, PluginView*> InstanceMap;
+
+static InstanceMap& instanceMap()
+{
+    static InstanceMap& map = *new InstanceMap;
+    return map;
+}
+
 static String scriptStringIfJavaScriptURL(const KURL& url)
 {
     if (!protocolIsJavaScript(url))
@@ -124,10 +134,10 @@
 
     updatePluginWidget();
 
-#if PLATFORM(WIN_OS) || PLATFORM(SYMBIAN)
+#if OS(WINDOWS) || OS(SYMBIAN)
     // On Windows and Symbian, always call plugin to change geometry.
     setNPWindowRect(rect);
-#elif XP_UNIX
+#elif defined(XP_UNIX)
     // On Unix, multiple calls to setNPWindow() in windowed mode causes Flash to crash
     if (m_mode == NP_FULL || !m_isWindowed)
         setNPWindowRect(rect);
@@ -144,11 +154,14 @@
     if (!m_plugin || m_isWindowed)
         return;
 
+    // Protect the plug-in from deletion while dispatching the event.
+    RefPtr<PluginView> protect(this);
+
     if (event->isMouseEvent())
         handleMouseEvent(static_cast<MouseEvent*>(event));
     else if (event->isKeyboardEvent())
         handleKeyboardEvent(static_cast<KeyboardEvent*>(event));
-#if defined(Q_WS_X11) && ENABLE(NETSCAPE_PLUGIN_API)
+#if defined(XP_UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
     else if (event->type() == eventNames().DOMFocusOutEvent)
         handleFocusOutEvent();
     else if (event->type() == eventNames().DOMFocusInEvent)
@@ -189,8 +202,11 @@
     if (!m_parentFrame->page())
         return false;
 
-    if (!m_parentFrame->page()->canStartPlugins()) {
-        m_parentFrame->page()->addUnstartedPlugin(this);
+    // We only delay starting the plug-in if we're going to kick off the load
+    // ourselves. Otherwise, the loader will try to deliver data before we've
+    // started the plug-in.
+    if (!m_loadManually && !m_parentFrame->page()->canStartMedia()) {
+        m_parentFrame->page()->addMediaCanStartListener(this);
         m_isWaitingToStart = true;
         return true;
     }
@@ -250,10 +266,21 @@
     return true;
 }
 
+void PluginView::mediaCanStart()
+{
+    ASSERT(!m_isStarted);
+    if (!start())
+        parentFrame()->loader()->client()->dispatchDidFailToStartPlugin(this);
+}
+
 PluginView::~PluginView()
 {
     LOG(Plugins, "PluginView::~PluginView()");
 
+    ASSERT(!m_lifeSupportTimer.isActive());
+
+    instanceMap().remove(m_instance);
+
     removeFromUnstartedListIfNecessary();
 
     stop();
@@ -279,7 +306,7 @@
     if (!m_parentFrame->page())
         return;
 
-    m_parentFrame->page()->removeUnstartedPlugin(this);
+    m_parentFrame->page()->removeMediaCanStartListener(this);
 }
 
 void PluginView::stop()
@@ -306,11 +333,10 @@
     JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
 
 #if ENABLE(NETSCAPE_PLUGIN_API)
-#if !PLATFORM(WX) // FIXME: Revisit this when implementing plugins for wx
 #ifdef XP_WIN
     // Unsubclass the window
     if (m_isWindowed) {
-#if PLATFORM(WINCE)
+#if OS(WINCE)
         WNDPROC currentWndProc = (WNDPROC)GetWindowLong(platformPluginWidget(), GWL_WNDPROC);
 
         if (currentWndProc == PluginViewWndProc)
@@ -319,11 +345,10 @@
         WNDPROC currentWndProc = (WNDPROC)GetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC);
 
         if (currentWndProc == PluginViewWndProc)
-            SetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC, (LONG)m_pluginWndProc);
+            SetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC, (LONG_PTR)m_pluginWndProc);
 #endif
     }
 #endif // XP_WIN
-#endif // !PLATFORM(WX)
 #endif // ENABLE(NETSCAPE_PLUGIN_API)
 
 #if !defined(XP_MACOSX)
@@ -421,7 +446,7 @@
         // if this is not a targeted request, create a stream for it. otherwise,
         // just pass it off to the loader
         if (targetFrameName.isEmpty()) {
-            RefPtr<PluginStream> stream = PluginStream::create(this, m_parentFrame, request->frameLoadRequest().resourceRequest(), request->sendNotification(), request->notifyData(), plugin()->pluginFuncs(), instance(), m_plugin->quirks());
+            RefPtr<PluginStream> stream = PluginStream::create(this, m_parentFrame.get(), request->frameLoadRequest().resourceRequest(), request->sendNotification(), request->notifyData(), plugin()->pluginFuncs(), instance(), m_plugin->quirks());
             m_streams.add(stream);
             stream->start();
         } else {
@@ -459,7 +484,7 @@
         if (getString(parentFrame->script(), result, resultString))
             cstr = resultString.utf8();
 
-        RefPtr<PluginStream> stream = PluginStream::create(this, m_parentFrame, request->frameLoadRequest().resourceRequest(), request->sendNotification(), request->notifyData(), plugin()->pluginFuncs(), instance(), m_plugin->quirks());
+        RefPtr<PluginStream> stream = PluginStream::create(this, m_parentFrame.get(), request->frameLoadRequest().resourceRequest(), request->sendNotification(), request->notifyData(), plugin()->pluginFuncs(), instance(), m_plugin->quirks());
         m_streams.add(stream);
         stream->sendJavaScriptStream(requestURL, cstr);
     }
@@ -508,12 +533,10 @@
     String jsString = scriptStringIfJavaScriptURL(url);
 
     if (!jsString.isNull()) {
-        Settings* settings = m_parentFrame->settings();
+        // Return NPERR_GENERIC_ERROR if JS is disabled. This is what Mozilla does.
+        if (!m_parentFrame->script()->canExecuteScripts(NotAboutToExecuteScript))
+            return NPERR_GENERIC_ERROR;
 
-        // Return NPERR_GENERIC_ERROR if JS is disabled. This is what Mozilla does.
-        if (!settings || !settings->isJavaScriptEnabled())
-            return NPERR_GENERIC_ERROR;
-        
         // For security reasons, only allow JS requests to be made on the frame that contains the plug-in.
         if (!targetFrameName.isNull() && m_parentFrame->tree()->find(targetFrameName) != m_parentFrame)
             return NPERR_INVALID_PARAM;
@@ -598,7 +621,7 @@
 void PluginView::status(const char* message)
 {
     if (Page* page = m_parentFrame->page())
-        page->chrome()->setStatusbarText(m_parentFrame, String(message));
+        page->chrome()->setStatusbarText(m_parentFrame.get(), String(message));
 }
 
 NPError PluginView::setValue(NPPVariable variable, void* value)
@@ -790,6 +813,8 @@
     , m_requestTimer(this, &PluginView::requestTimerFired)
     , m_invalidateTimer(this, &PluginView::invalidateTimerFired)
     , m_popPopupsStateTimer(this, &PluginView::popPopupsStateTimerFired)
+    , m_lifeSupportTimer(this, &PluginView::lifeSupportTimerFired)
+    , m_mode(loadManually ? NP_FULL : NP_EMBED)
     , m_paramNames(0)
     , m_paramValues(0)
     , m_mimeType(mimeType)
@@ -801,25 +826,27 @@
     , m_isTransparent(false)
     , m_haveInitialized(false)
     , m_isWaitingToStart(false)
-#if defined(XP_UNIX) || defined(Q_WS_X11)
+#if defined(XP_UNIX)
     , m_needsXEmbed(false)
 #endif
-#if PLATFORM(WIN_OS) && !PLATFORM(WX) && ENABLE(NETSCAPE_PLUGIN_API)
+#if OS(WINDOWS) && ENABLE(NETSCAPE_PLUGIN_API)
     , m_pluginWndProc(0)
     , m_lastMessage(0)
     , m_isCallingPluginWndProc(false)
     , m_wmPrintHDC(0)
     , m_haveUpdatedPluginWidget(false)
 #endif
-#if (PLATFORM(QT) && PLATFORM(WIN_OS)) || defined(XP_MACOSX)
+#if (PLATFORM(QT) && OS(WINDOWS)) || defined(XP_MACOSX)
     , m_window(0)
 #endif
 #if defined(XP_MACOSX)
     , m_drawingModel(NPDrawingModel(-1))
     , m_eventModel(NPEventModel(-1))
+    , m_contextRef(0)
+    , m_fakeWindow(0)
 #endif
-#if defined(Q_WS_X11) && ENABLE(NETSCAPE_PLUGIN_API)
-    , m_hasPendingGeometryChange(false)
+#if defined(XP_UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
+    , m_hasPendingGeometryChange(true)
     , m_drawable(0)
     , m_visual(0)
     , m_colormap(0)
@@ -840,6 +867,8 @@
     m_instance->ndata = this;
     m_instance->pdata = 0;
 
+    instanceMap().add(m_instance, this);
+
     setParameters(paramNames, paramValues);
 
     memset(&m_npWindow, 0, sizeof(m_npWindow));
@@ -847,8 +876,6 @@
     memset(&m_npCgContext, 0, sizeof(m_npCgContext));
 #endif
 
-    m_mode = m_loadManually ? NP_FULL : NP_EMBED;
-
     resize(size);
 }
 
@@ -868,7 +895,7 @@
     ASSERT(m_loadManually);
     ASSERT(!m_manualStream);
 
-    m_manualStream = PluginStream::create(this, m_parentFrame, m_parentFrame->loader()->activeDocumentLoader()->request(), false, 0, plugin()->pluginFuncs(), instance(), m_plugin->quirks());
+    m_manualStream = PluginStream::create(this, m_parentFrame.get(), m_parentFrame->loader()->activeDocumentLoader()->request(), false, 0, plugin()->pluginFuncs(), instance(), m_plugin->quirks());
     m_manualStream->setLoadManually(true);
 
     m_manualStream->didReceiveResponse(0, response);
@@ -1198,7 +1225,7 @@
 
     context->save();
     context->clip(windowClipRect());
-    context->drawImage(nullPluginImage.get(), imageRect.location());
+    context->drawImage(nullPluginImage.get(), DeviceColorSpace, imageRect.location());
     context->restore();
 }
 
@@ -1209,7 +1236,7 @@
         "Windows; U; Windows NT 5.1;"
 #elif defined(XP_UNIX)
 // The Gtk port uses X11 plugins in Mac.
-#if PLATFORM(DARWIN) && PLATFORM(GTK)
+#if OS(DARWIN) && PLATFORM(GTK)
     "X11; U; Intel Mac OS X;"
 #else
     "X11; U; Linux i686;"
@@ -1241,4 +1268,120 @@
     return m_element;
 }
 
+String PluginView::pluginName() const
+{
+    return m_plugin->name();
+}
+
+void PluginView::lifeSupportTimerFired(Timer<PluginView>*)
+{
+    deref();
+}
+
+void PluginView::keepAlive()
+{
+    if (m_lifeSupportTimer.isActive())
+        return;
+
+    ref();
+    m_lifeSupportTimer.startOneShot(0);
+}
+
+#if ENABLE(NETSCAPE_PLUGIN_API)
+void PluginView::keepAlive(NPP instance)
+{
+    PluginView* view = instanceMap().get(instance);
+    if (!view)
+        return;
+
+    view->keepAlive();
+}
+
+NPError PluginView::getValueStatic(NPNVariable variable, void* value)
+{
+    LOG(Plugins, "PluginView::getValueStatic(%s)", prettyNameForNPNVariable(variable).data());
+
+    NPError result;
+    if (platformGetValueStatic(variable, value, &result))
+        return result;
+
+    return NPERR_GENERIC_ERROR;
+}
+
+NPError PluginView::getValue(NPNVariable variable, void* value)
+{
+    LOG(Plugins, "PluginView::getValue(%s)", prettyNameForNPNVariable(variable).data());
+
+    NPError result;
+    if (platformGetValue(variable, value, &result))
+        return result;
+
+    if (platformGetValueStatic(variable, value, &result))
+        return result;
+
+    switch (variable) {
+    case NPNVWindowNPObject: {
+        if (m_isJavaScriptPaused)
+            return NPERR_GENERIC_ERROR;
+
+        NPObject* windowScriptObject = m_parentFrame->script()->windowScriptNPObject();
+
+        // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugin/npruntime.html>
+        if (windowScriptObject)
+            _NPN_RetainObject(windowScriptObject);
+
+        void** v = (void**)value;
+        *v = windowScriptObject;
+
+        return NPERR_NO_ERROR;
+    }
+
+    case NPNVPluginElementNPObject: {
+        if (m_isJavaScriptPaused)
+            return NPERR_GENERIC_ERROR;
+
+        NPObject* pluginScriptObject = 0;
+
+        if (m_element->hasTagName(appletTag) || m_element->hasTagName(embedTag) || m_element->hasTagName(objectTag))
+            pluginScriptObject = static_cast<HTMLPlugInElement*>(m_element)->getNPObject();
+
+        // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugin/npruntime.html>
+        if (pluginScriptObject)
+            _NPN_RetainObject(pluginScriptObject);
+
+        void** v = (void**)value;
+        *v = pluginScriptObject;
+
+        return NPERR_NO_ERROR;
+    }
+
+    case NPNVprivateModeBool: {
+        Page* page = m_parentFrame->page();
+        if (!page)
+            return NPERR_GENERIC_ERROR;
+        *((NPBool*)value) = !page->settings() || page->settings()->privateBrowsingEnabled();
+        return NPERR_NO_ERROR;
+    }
+
+    default:
+        return NPERR_GENERIC_ERROR;
+    }
+}
+#endif
+
+void PluginView::privateBrowsingStateChanged(bool privateBrowsingEnabled)
+{
+    NPP_SetValueProcPtr setValue = m_plugin->pluginFuncs()->setvalue;
+    if (!setValue)
+        return;
+
+    PluginView::setCurrentPluginView(this);
+    JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
+    setCallingPlugin(true);
+    NPBool value = privateBrowsingEnabled;
+    setValue(m_instance, NPNVprivateModeBool, &value);
+    setCallingPlugin(false);
+    PluginView::setCurrentPluginView(0);
+}
+
 } // namespace WebCore