summaryrefslogtreecommitdiffstats
path: root/WebCore/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/plugins')
-rw-r--r--WebCore/plugins/PluginDatabase.cpp16
-rw-r--r--WebCore/plugins/PluginDatabase.h9
-rw-r--r--WebCore/plugins/PluginDatabaseClient.h42
-rw-r--r--WebCore/plugins/PluginPackage.cpp1
-rw-r--r--WebCore/plugins/PluginQuirkSet.h1
-rw-r--r--WebCore/plugins/PluginView.cpp182
-rw-r--r--WebCore/plugins/PluginView.h29
-rw-r--r--WebCore/plugins/PluginViewNone.cpp13
-rw-r--r--WebCore/plugins/android/PluginViewAndroid.cpp76
-rw-r--r--WebCore/plugins/gtk/PluginViewGtk.cpp83
-rw-r--r--WebCore/plugins/mac/PluginPackageMac.cpp3
-rw-r--r--WebCore/plugins/mac/PluginViewMac.cpp84
-rw-r--r--WebCore/plugins/qt/PluginPackageQt.cpp18
-rw-r--r--WebCore/plugins/qt/PluginViewQt.cpp516
-rw-r--r--WebCore/plugins/win/PaintHooks.asm50
-rw-r--r--WebCore/plugins/win/PluginViewWin.cpp145
16 files changed, 902 insertions, 366 deletions
diff --git a/WebCore/plugins/PluginDatabase.cpp b/WebCore/plugins/PluginDatabase.cpp
index 414f1ba..f7304df 100644
--- a/WebCore/plugins/PluginDatabase.cpp
+++ b/WebCore/plugins/PluginDatabase.cpp
@@ -29,6 +29,7 @@
#include "Frame.h"
#include "KURL.h"
+#include "PluginDatabaseClient.h"
#include "PluginPackage.h"
#include <stdlib.h>
@@ -41,6 +42,11 @@ namespace WebCore {
typedef HashMap<String, RefPtr<PluginPackage> > PluginPackageByNameMap;
+PluginDatabase::PluginDatabase()
+ : m_client(0)
+{
+}
+
PluginDatabase* PluginDatabase::installedPlugins(bool populate)
{
static PluginDatabase* plugins = 0;
@@ -116,9 +122,11 @@ bool PluginDatabase::refresh()
remove(oldPackage.get());
}
- RefPtr<PluginPackage> package = PluginPackage::createPackage(*it, lastModified);
- if (package && add(package.release()))
- pluginSetChanged = true;
+ if (!m_client || m_client->shouldLoadPluginAtPath(*it)) {
+ RefPtr<PluginPackage> package = PluginPackage::createPackage(*it, lastModified);
+ if (package && (!m_client || m_client->shouldLoadPluginPackage(package.get())) && add(package.release()))
+ pluginSetChanged = true;
+ }
}
// Cache all the paths we found with their timestamps for next time.
@@ -352,6 +360,8 @@ Vector<String> PluginDatabase::defaultPluginDirectories()
paths.append("/usr/lib/netscape/plugins-libc6");
paths.append("/usr/lib64/netscape/plugins");
paths.append("/usr/lib64/mozilla/plugins");
+ paths.append("/usr/lib/nsbrowser/plugins");
+ paths.append("/usr/lib64/nsbrowser/plugins");
String mozHome(getenv("MOZILLA_HOME"));
mozHome.append("/plugins");
diff --git a/WebCore/plugins/PluginDatabase.h b/WebCore/plugins/PluginDatabase.h
index 14a6fb3..fe74682 100644
--- a/WebCore/plugins/PluginDatabase.h
+++ b/WebCore/plugins/PluginDatabase.h
@@ -46,12 +46,15 @@ namespace WebCore {
class Frame;
class IntSize;
class KURL;
+ class PluginDatabaseClient;
class PluginPackage;
typedef HashSet<RefPtr<PluginPackage>, PluginPackageHash> PluginSet;
class PluginDatabase {
public:
+ PluginDatabase();
+
// The first call to installedPlugins creates the plugin database
// and by default populates it with the plugins installed on the system.
// For testing purposes, it is possible to not populate the database
@@ -78,6 +81,11 @@ namespace WebCore {
m_pluginDirectories = directories;
}
+ void setClient(PluginDatabaseClient* client)
+ {
+ m_client = client;
+ }
+
static Vector<String> defaultPluginDirectories();
Vector<String> pluginDirectories() const { return m_pluginDirectories; }
@@ -103,6 +111,7 @@ namespace WebCore {
friend class ::android::WebSettings;
#endif
HashMap<String, RefPtr<PluginPackage> > m_preferredPlugins;
+ PluginDatabaseClient* m_client;
};
} // namespace WebCore
diff --git a/WebCore/plugins/PluginDatabaseClient.h b/WebCore/plugins/PluginDatabaseClient.h
new file mode 100644
index 0000000..b19ab83
--- /dev/null
+++ b/WebCore/plugins/PluginDatabaseClient.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2007 Marius Renn <damarvy@gmail.com> All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef PluginDatabaseClient_h
+#define PluginDatabaseClient_h
+
+namespace WebCore {
+
+ class PluginPackage;
+ class String;
+
+ class PluginDatabaseClient {
+ public:
+ virtual ~PluginDatabaseClient() { }
+ virtual bool shouldLoadPluginAtPath(const String&) = 0;
+ virtual bool shouldLoadPluginPackage(const PluginPackage*) = 0;
+ };
+
+} // namespace WebCore
+
+#endif // PluginDatabaseClient_h
diff --git a/WebCore/plugins/PluginPackage.cpp b/WebCore/plugins/PluginPackage.cpp
index 7e8885d..258cbb7 100644
--- a/WebCore/plugins/PluginPackage.cpp
+++ b/WebCore/plugins/PluginPackage.cpp
@@ -189,6 +189,7 @@ void PluginPackage::determineQuirks(const String& mimeType)
#if PLATFORM(QT)
m_quirks.add(PluginQuirkRequiresGtkToolKit);
#endif
+ m_quirks.add(PluginQuirkRequiresDefaultScreenDepth);
} else {
// Flash 9 and older requests windowless plugins if we return a mozilla user agent
m_quirks.add(PluginQuirkWantsMozillaUserAgent);
diff --git a/WebCore/plugins/PluginQuirkSet.h b/WebCore/plugins/PluginQuirkSet.h
index b652c6e..de29baf 100644
--- a/WebCore/plugins/PluginQuirkSet.h
+++ b/WebCore/plugins/PluginQuirkSet.h
@@ -46,6 +46,7 @@ namespace WebCore {
PluginQuirkDontSetNullWindowHandleOnDestroy = 1 << 10,
PluginQuirkDontAllowMultipleInstances = 1 << 11,
PluginQuirkRequiresGtkToolKit = 1 << 12,
+ PluginQuirkRequiresDefaultScreenDepth = 1 << 13
};
class PluginQuirkSet {
diff --git a/WebCore/plugins/PluginView.cpp b/WebCore/plugins/PluginView.cpp
index c6b0cae..13d8511 100644
--- a/WebCore/plugins/PluginView.cpp
+++ b/WebCore/plugins/PluginView.cpp
@@ -51,6 +51,7 @@
#include "PluginPackage.h"
#include "ScriptController.h"
#include "ScriptValue.h"
+#include "SecurityOrigin.h"
#include "PluginDatabase.h"
#include "PluginDebug.h"
#include "PluginMainThreadScheduler.h"
@@ -59,6 +60,8 @@
#include "RenderObject.h"
#include "npruntime_impl.h"
#include "Settings.h"
+#include <wtf/ASCIICType.h>
+
#if defined(ANDROID_PLUGINS)
#include "TouchEvent.h"
#endif
@@ -71,11 +74,7 @@
#include "runtime.h"
#include <runtime/JSLock.h>
#include <runtime/JSValue.h>
-#endif
-
-#include <wtf/ASCIICType.h>
-#if USE(JSC)
using JSC::ExecState;
using JSC::JSLock;
using JSC::JSObject;
@@ -143,8 +142,8 @@ void PluginView::setFrameRect(const IntRect& rect)
// On Windows, always call plugin to change geometry.
setNPWindowRect(rect);
#elif XP_UNIX
- // On Unix, only call plugin if it's full-page.
- if (m_mode == NP_FULL)
+ // On Unix, multiple calls to setNPWindow() in windowed mode causes Flash to crash
+ if (m_mode == NP_FULL || !m_isWindowed)
setNPWindowRect(rect);
#endif
}
@@ -166,7 +165,59 @@ void PluginView::handleEvent(Event* event)
#if defined(ANDROID_PLUGINS)
else if (event->isTouchEvent())
handleTouchEvent(static_cast<TouchEvent*>(event));
+ else if (event->type() == eventNames().DOMFocusOutEvent)
+ handleFocusEvent(false);
+ else if (event->type() == eventNames().DOMFocusInEvent)
+ handleFocusEvent(true);
#endif
+#if defined(Q_WS_X11)
+ else if (event->type() == eventNames().DOMFocusOutEvent)
+ handleFocusOutEvent();
+ else if (event->type() == eventNames().DOMFocusInEvent)
+ handleFocusInEvent();
+#endif
+}
+
+void PluginView::init()
+{
+ if (m_haveInitialized)
+ return;
+
+ m_haveInitialized = true;
+
+ if (!m_plugin) {
+ ASSERT(m_status == PluginStatusCanNotFindPlugin);
+ return;
+ }
+
+ LOG(Plugins, "PluginView::init(): Initializing plug-in '%s'", m_plugin->name().utf8().data());
+
+ if (!m_plugin->load()) {
+ m_plugin = 0;
+ m_status = PluginStatusCanNotLoadPlugin;
+ return;
+ }
+
+ if (!startOrAddToUnstartedList()) {
+ m_status = PluginStatusCanNotLoadPlugin;
+ return;
+ }
+
+ m_status = PluginStatusLoadedSuccessfully;
+}
+
+bool PluginView::startOrAddToUnstartedList()
+{
+ if (!m_parentFrame->page())
+ return false;
+
+ if (!m_parentFrame->page()->canStartPlugins()) {
+ m_parentFrame->page()->addUnstartedPlugin(this);
+ m_isWaitingToStart = true;
+ return true;
+ }
+
+ return start();
}
@@ -212,16 +263,63 @@ bool PluginView::start()
m_status = PluginStatusLoadedSuccessfully;
- platformStart();
+ if (!platformStart())
+ m_status = PluginStatusCanNotLoadPlugin;
+
+ if (m_status != PluginStatusLoadedSuccessfully)
+ return false;
+
+ if (parentFrame()->page())
+ parentFrame()->page()->didStartPlugin(this);
return true;
}
+PluginView::~PluginView()
+{
+ LOG(Plugins, "PluginView::~PluginView()");
+
+ removeFromUnstartedListIfNecessary();
+
+ stop();
+
+ deleteAllValues(m_requests);
+
+ freeStringArray(m_paramNames, m_paramCount);
+ freeStringArray(m_paramValues, m_paramCount);
+
+ platformDestroy();
+
+ m_parentFrame->script()->cleanupScriptObjectsForPlugin(this);
+
+#if PLATFORM(ANDROID)
+ // Since we have no legacy plugins to check, we ignore the quirks check.
+ if (m_plugin)
+#else
+ if (m_plugin && !(m_plugin->quirks().contains(PluginQuirkDontUnloadPlugin)))
+#endif
+ m_plugin->unload();
+}
+
+void PluginView::removeFromUnstartedListIfNecessary()
+{
+ if (!m_isWaitingToStart)
+ return;
+
+ if (!m_parentFrame->page())
+ return;
+
+ m_parentFrame->page()->removeUnstartedPlugin(this);
+}
+
void PluginView::stop()
{
if (!m_isStarted)
return;
+ if (parentFrame()->page())
+ parentFrame()->page()->didStopPlugin(this);
+
LOG(Plugins, "PluginView::stop(): Stopping plug-in '%s'", m_plugin->name().utf8().data());
HashSet<RefPtr<PluginStream> > streams = m_streams;
@@ -237,6 +335,9 @@ void PluginView::stop()
#if USE(JSC)
JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
#endif
+
+#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) {
@@ -253,6 +354,8 @@ void PluginView::stop()
#endif
}
#endif // XP_WIN
+#endif // !PLATFORM(WX)
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
#if !defined(XP_MACOSX)
// Clear the window
@@ -332,33 +435,11 @@ static bool getString(ScriptController* proxy, JSValue result, String& string)
}
#endif
-bool PluginView::startOrAddToUnstartedList()
-{
- if (!m_parentFrame->page())
- return false;
-
- if (!m_parentFrame->page()->canStartPlugins()) {
- m_parentFrame->page()->addUnstartedPlugin(this);
- m_isWaitingToStart = true;
- return true;
- }
-
- return start();
-}
-
-void PluginView::removeFromUnstartedListIfNecessary()
+void PluginView::performRequest(PluginRequest* request)
{
- if (!m_isWaitingToStart)
- return;
-
- if (!m_parentFrame->page())
+ if (!m_isStarted)
return;
- m_parentFrame->page()->removeUnstartedPlugin(this);
-}
-
-void PluginView::performRequest(PluginRequest* request)
-{
// don't let a plugin start any loads if it is no longer part of a document that is being
// displayed unless the loads are in the same frame as the plugin.
const String& targetFrameName = request->frameLoadRequest().frameName();
@@ -401,7 +482,7 @@ void PluginView::performRequest(PluginRequest* request)
// Targeted JavaScript requests are only allowed on the frame that contains the JavaScript plugin
// and this has been made sure in ::load.
ASSERT(targetFrameName.isEmpty() || m_parentFrame->tree()->find(targetFrameName) == m_parentFrame);
-
+
#if USE(JSC)
// Executing a script can cause the plugin view to be destroyed, so we keep a reference to the parent frame.
RefPtr<Frame> parentFrame = m_parentFrame;
@@ -473,9 +554,8 @@ NPError PluginView::load(const FrameLoadRequest& frameLoadRequest, bool sendNoti
// 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;
- } else if (!FrameLoader::canLoad(url, String(), m_parentFrame->document())) {
+ } else if (!SecurityOrigin::canLoad(url, String(), m_parentFrame->document()))
return NPERR_GENERIC_ERROR;
- }
PluginRequest* request = new PluginRequest(frameLoadRequest, sendNotification, notifyData, arePopupsAllowed());
scheduleRequest(request);
@@ -794,7 +874,7 @@ PluginView::PluginView(Frame* parentFrame, const IntSize& size, PluginPackage* p
, m_isTransparent(false)
, m_haveInitialized(false)
, m_isWaitingToStart(false)
-#if PLATFORM(GTK) || defined(Q_WS_X11)
+#if defined(XP_UNIX) || defined(Q_WS_X11)
, m_needsXEmbed(false)
#endif
#if PLATFORM(WIN_OS) && !PLATFORM(WX) && ENABLE(NETSCAPE_PLUGIN_API)
@@ -811,6 +891,13 @@ PluginView::PluginView(Frame* parentFrame, const IntSize& size, PluginPackage* p
, m_drawingModel(NPDrawingModel(-1))
, m_eventModel(NPEventModel(-1))
#endif
+#if defined(Q_WS_X11)
+ , m_hasPendingGeometryChange(false)
+ , m_drawable(0)
+ , m_visual(0)
+ , m_colormap(0)
+ , m_pluginDisplay(0)
+#endif
, m_loadManually(loadManually)
, m_manualStream(0)
, m_isJavaScriptPaused(false)
@@ -1184,9 +1271,8 @@ void PluginView::invalidateWindowlessPluginRect(const IntRect& rect)
void PluginView::paintMissingPluginIcon(GraphicsContext* context, const IntRect& rect)
{
static RefPtr<Image> nullPluginImage;
- if (!nullPluginImage) {
+ if (!nullPluginImage)
nullPluginImage = Image::loadPlatformResource("nullPlugin");
- }
IntRect imageRect(frameRect().x(), frameRect().y(), nullPluginImage->width(), nullPluginImage->height());
@@ -1194,11 +1280,10 @@ void PluginView::paintMissingPluginIcon(GraphicsContext* context, const IntRect&
int yOffset = (frameRect().height() - imageRect.height()) / 2;
imageRect.move(xOffset, yOffset);
-
- if (!rect.intersects(imageRect)) {
+
+ if (!rect.intersects(imageRect))
return;
- }
-
+
context->save();
context->clip(windowClipRect());
context->drawImage(nullPluginImage.get(), imageRect.location());
@@ -1211,7 +1296,12 @@ static const char* MozillaUserAgent = "Mozilla/5.0 ("
#elif defined(XP_WIN)
"Windows; U; Windows NT 5.1;"
#elif defined(XP_UNIX)
- "X11; U; Linux i686;"
+// The Gtk port uses X11 plugins in Mac.
+#if PLATFORM(DARWIN) && PLATFORM(GTK)
+ "X11; U; Intel Mac OS X;"
+#else
+ "X11; U; Linux i686;"
+#endif
#endif
" en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0";
@@ -1221,8 +1311,10 @@ const char* PluginView::userAgent()
if (m_plugin->quirks().contains(PluginQuirkWantsMozillaUserAgent))
return MozillaUserAgent;
#endif
+
if (m_userAgent.isNull())
m_userAgent = m_parentFrame->loader()->userAgent(m_url).utf8();
+
return m_userAgent.data();
}
@@ -1233,4 +1325,10 @@ const char* PluginView::userAgentStatic()
}
#endif
+
+Node* PluginView::node() const
+{
+ return m_element;
+}
+
} // namespace WebCore
diff --git a/WebCore/plugins/PluginView.h b/WebCore/plugins/PluginView.h
index 5c39535..b385d41 100644
--- a/WebCore/plugins/PluginView.h
+++ b/WebCore/plugins/PluginView.h
@@ -30,6 +30,7 @@
#include "CString.h"
#include "FrameLoadRequest.h"
+#include "HaltablePlugin.h"
#include "IntRect.h"
#include "KURL.h"
#include "PlatformString.h"
@@ -120,7 +121,7 @@ namespace WebCore {
virtual void didFail(const ResourceError&) = 0;
};
- class PluginView : public Widget, private PluginStreamClient, public PluginManualLoader {
+ class PluginView : public Widget, private PluginStreamClient, public PluginManualLoader, private HaltablePlugin {
public:
static PassRefPtr<PluginView> create(Frame* parentFrame, const IntSize&, Element*, const KURL&, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually);
virtual ~PluginView();
@@ -216,6 +217,11 @@ namespace WebCore {
void didFinishLoading();
void didFail(const ResourceError&);
+ // HaltablePlugin
+ virtual void halt();
+ virtual void restart();
+ virtual Node* node() const;
+
static bool isCallingPlugin();
#ifdef ANDROID_PLUGINS
@@ -232,8 +238,9 @@ namespace WebCore {
bool startOrAddToUnstartedList();
void removeFromUnstartedListIfNecessary();
void init();
- void platformStart();
+ bool platformStart();
void stop();
+ void platformDestroy();
static void setCurrentPluginView(PluginView*);
NPError load(const FrameLoadRequest&, bool sendNotification, void* notifyData);
NPError handlePost(const char* url, const char* target, uint32 len, const char* buf, bool file, void* notifyData, bool sendNotification, bool allowHeaders);
@@ -276,8 +283,13 @@ namespace WebCore {
void handleKeyboardEvent(KeyboardEvent*);
void handleMouseEvent(MouseEvent*);
+#if defined(Q_WS_X11)
+ void handleFocusInEvent();
+ void handleFocusOutEvent();
+#endif
#ifdef ANDROID_PLUGINS
+ void handleFocusEvent(bool hasFocus);
void handleTouchEvent(TouchEvent*);
// called at the end of the base constructor
void platformInit();
@@ -299,7 +311,7 @@ namespace WebCore {
NPP m_instance;
NPP_t m_instanceStruct;
NPWindow m_npWindow;
-
+
Vector<bool, 4> m_popupStateStack;
HashSet<RefPtr<PluginStream> > m_streams;
@@ -310,7 +322,7 @@ namespace WebCore {
bool m_haveInitialized;
bool m_isWaitingToStart;
-#if PLATFORM(GTK) || defined(Q_WS_X11)
+#if defined(XP_UNIX) || defined(Q_WS_X11)
bool m_needsXEmbed;
#endif
@@ -340,12 +352,13 @@ public:
PlatformPluginWidget platformPluginWidget() const { return m_window; } // MANUAL MERGE FIXME
#else
public:
+ void setPlatformPluginWidget(PlatformPluginWidget widget) { setPlatformWidget(widget); }
PlatformPluginWidget platformPluginWidget() const { return platformWidget(); }
#endif
private:
-#if PLATFORM(GTK) || defined(Q_WS_X11)
+#if defined(XP_UNIX) || defined(Q_WS_X11)
void setNPWindowIfNeeded();
#elif defined(XP_MACOSX)
NP_CGContext m_npCgContext;
@@ -360,6 +373,12 @@ private:
#if defined(Q_WS_X11)
bool m_hasPendingGeometryChange;
+ Pixmap m_drawable;
+ Visual* m_visual;
+ Colormap m_colormap;
+ Display* m_pluginDisplay;
+
+ void initXEvent(XEvent* event);
#endif
IntRect m_clipRect; // The clip rect to apply to a windowed plug-in
diff --git a/WebCore/plugins/PluginViewNone.cpp b/WebCore/plugins/PluginViewNone.cpp
index be79567..d4601d4 100644
--- a/WebCore/plugins/PluginViewNone.cpp
+++ b/WebCore/plugins/PluginViewNone.cpp
@@ -114,12 +114,14 @@ void PluginView::forceRedraw()
notImplemented();
}
-PluginView::~PluginView()
+bool PluginView::platformStart()
{
notImplemented();
+
+ return true;
}
-void PluginView::init()
+void PluginView::platformDestroy()
{
notImplemented();
}
@@ -134,9 +136,12 @@ void PluginView::updatePluginWidget()
notImplemented();
}
-void PluginView::platformStart()
+void PluginView::halt()
+{
+}
+
+void PluginView::restart()
{
- notImplemented();
}
} // namespace WebCore
diff --git a/WebCore/plugins/android/PluginViewAndroid.cpp b/WebCore/plugins/android/PluginViewAndroid.cpp
index 7d10993..529458b 100644
--- a/WebCore/plugins/android/PluginViewAndroid.cpp
+++ b/WebCore/plugins/android/PluginViewAndroid.cpp
@@ -163,58 +163,18 @@ void PluginView::platformInit()
m_npWindow.window = 0;
}
-void PluginView::platformStart()
+bool PluginView::platformStart()
{
- notImplemented();
+ android::WebViewCore* c = android::WebViewCore::getWebViewCore(this->parent());
+ m_window->init(c);
+ return true;
}
-PluginView::~PluginView()
+void PluginView::platformDestroy()
{
- stop();
-
- deleteAllValues(m_requests);
-
- freeStringArray(m_paramNames, m_paramCount);
- freeStringArray(m_paramValues, m_paramCount);
-
- m_parentFrame->script()->cleanupScriptObjectsForPlugin(this);
-
-// Since we have no legacy plugins to check, we ignore the quirks check
-// if (m_plugin && !m_plugin->quirks().contains(PluginQuirkDontUnloadPlugin))
- if (m_plugin) {
- m_plugin->unload();
- }
delete m_window;
}
-void PluginView::init()
-{
- if (m_haveInitialized)
- return;
- m_haveInitialized = true;
-
- android::WebViewCore* c = android::WebViewCore::getWebViewCore(this->parent());
- m_window->init(c);
-
- if (!m_plugin) {
- ASSERT(m_status == PluginStatusCanNotFindPlugin);
- return;
- }
-
- if (!m_plugin->load()) {
- m_plugin = 0;
- m_status = PluginStatusCanNotLoadPlugin;
- return;
- }
-
- if (!start()) {
- m_status = PluginStatusCanNotLoadPlugin;
- return;
- }
-
- m_status = PluginStatusLoadedSuccessfully;
-}
-
void PluginView::handleTouchEvent(TouchEvent* event)
{
if (!m_window->isAcceptingEvent(kTouch_ANPEventFlag))
@@ -298,6 +258,20 @@ static ANPKeyModifier make_modifiers(bool shift, bool alt) {
return mod;
}
+void PluginView::handleFocusEvent(bool hasFocus)
+{
+ ANPEvent evt;
+ SkANP::InitEvent(&evt, kLifecycle_ANPEventType);
+ evt.data.lifecycle.action = hasFocus ? kGainFocus_ANPLifecycleAction :
+ kLoseFocus_ANPLifecycleAction;
+ m_window->sendEvent(evt);
+
+ // redraw the plugin which subsequently invalidates the nav cache
+ IntRect rect = IntRect(m_npWindow.x, m_npWindow.y,
+ m_npWindow.width, m_npWindow.height);
+ m_window->webViewCore()->contentInvalidate(rect);
+}
+
void PluginView::handleKeyboardEvent(KeyboardEvent* event)
{
if (!m_window->isAcceptingEvent(kKey_ANPEventFlag))
@@ -359,6 +333,9 @@ void PluginView::handleKeyboardEvent(KeyboardEvent* event)
if (m_plugin->pluginFuncs()->event(m_instance, &evt)) {
event->setDefaultHandled();
+ } else {
+ // remove the plugin from the document's focus
+ m_parentFrame->document()->focusedNodeRemoved();
}
}
@@ -538,7 +515,6 @@ void PluginView::invalidateRect(NPRect* rect)
}
m_window->inval(r, true);
-// android::WebViewCore::getWebViewCore(parent())->contentInvalidate(r);
}
void PluginView::invalidateRegion(NPRegion region)
@@ -601,4 +577,12 @@ void PluginView::setParentVisible(bool) {
notImplemented();
}
+void PluginView::halt() {
+ notImplemented();
+}
+
+void PluginView::restart() {
+ notImplemented();
+}
+
} // namespace WebCore
diff --git a/WebCore/plugins/gtk/PluginViewGtk.cpp b/WebCore/plugins/gtk/PluginViewGtk.cpp
index 4dd2b32..bc3a622 100644
--- a/WebCore/plugins/gtk/PluginViewGtk.cpp
+++ b/WebCore/plugins/gtk/PluginViewGtk.cpp
@@ -59,11 +59,10 @@
#include <gdkconfig.h>
#include <gtk/gtk.h>
-#if PLATFORM(X11)
+#if defined(XP_UNIX)
#include "gtk2xtbin.h"
#include <gdk/gdkx.h>
-#endif
-#ifdef GDK_WINDOWING_WIN32
+#elif defined(GDK_WINDOWING_WIN32)
#include "PluginMessageThrottlerWin.h"
#include <gdk/gdkwin32.h>
#endif
@@ -228,7 +227,7 @@ void PluginView::setNPWindowIfNeeded()
GtkAllocation allocation = { m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height() };
gtk_widget_size_allocate(platformPluginWidget(), &allocation);
-#if PLATFORM(X11)
+#if PLATFORM(XP_UNIX)
if (!m_needsXEmbed) {
gtk_xtbin_set_position(GTK_XTBIN(platformPluginWidget()), m_windowRect.x(), m_windowRect.y());
gtk_xtbin_resize(platformPluginWidget(), m_windowRect.width(), m_windowRect.height());
@@ -293,7 +292,7 @@ NPError PluginView::getValueStatic(NPNVariable variable, void* value)
switch (variable) {
case NPNVToolkit:
-#if PLATFORM(GTK)
+#if defined(XP_UNIX)
*static_cast<uint32*>(value) = 2;
#else
*static_cast<uint32*>(value) = 0;
@@ -301,7 +300,7 @@ NPError PluginView::getValueStatic(NPNVariable variable, void* value)
return NPERR_NO_ERROR;
case NPNVSupportsXEmbedBool:
-#if PLATFORM(X11)
+#if defined(XP_UNIX)
*static_cast<NPBool*>(value) = true;
#else
*static_cast<NPBool*>(value) = false;
@@ -323,7 +322,7 @@ NPError PluginView::getValue(NPNVariable variable, void* value)
switch (variable) {
case NPNVxDisplay:
-#if PLATFORM(X11)
+#if defined(XP_UNIX)
if (m_needsXEmbed)
*(void **)value = (void *)GDK_DISPLAY();
else
@@ -333,7 +332,7 @@ NPError PluginView::getValue(NPNVariable variable, void* value)
return NPERR_GENERIC_ERROR;
#endif
-#if PLATFORM(X11)
+#if PLATFORM(XP_UNIX)
case NPNVxtAppContext:
if (!m_needsXEmbed) {
*(void **)value = XtDisplayToApplicationContext (GTK_XTBIN(platformPluginWidget())->xtclient.xtdisplay);
@@ -381,13 +380,13 @@ NPError PluginView::getValue(NPNVariable variable, void* value)
#endif
case NPNVnetscapeWindow: {
-#if PLATFORM(X11)
+#if defined(XP_UNIX)
void* w = reinterpret_cast<void*>(value);
- *((XID *)w) = GDK_WINDOW_XWINDOW(m_parentFrame->view()->hostWindow()->platformWindow()->window);
+ *((XID *)w) = GDK_WINDOW_XWINDOW(m_parentFrame->view()->hostWindow()->platformPageClient()->window);
#endif
#ifdef GDK_WINDOWING_WIN32
HGDIOBJ* w = reinterpret_cast<HGDIOBJ*>(value);
- *w = GDK_WINDOW_HWND(m_parentFrame->view()->hostWindow()->platformWindow()->window);
+ *w = GDK_WINDOW_HWND(m_parentFrame->view()->hostWindow()->platformPageClient()->window);
#endif
return NPERR_NO_ERROR;
}
@@ -429,22 +428,7 @@ void PluginView::forceRedraw()
if (m_isWindowed)
gtk_widget_queue_draw(platformPluginWidget());
else
- gtk_widget_queue_draw(m_parentFrame->view()->hostWindow()->platformWindow());
-}
-
-PluginView::~PluginView()
-{
- stop();
-
- deleteAllValues(m_requests);
-
- freeStringArray(m_paramNames, m_paramCount);
- freeStringArray(m_paramValues, m_paramCount);
-
- m_parentFrame->script()->cleanupScriptObjectsForPlugin(this);
-
- if (m_plugin && !(m_plugin->quirks().contains(PluginQuirkDontUnloadPlugin)))
- m_plugin->unload();
+ gtk_widget_queue_draw(m_parentFrame->view()->hostWindow()->platformPageClient());
}
static gboolean
@@ -453,27 +437,10 @@ plug_removed_cb(GtkSocket *socket, gpointer)
return TRUE;
}
-void PluginView::init()
+bool PluginView::platformStart()
{
- if (m_haveInitialized)
- return;
- m_haveInitialized = true;
-
- if (!m_plugin) {
- ASSERT(m_status == PluginStatusCanNotFindPlugin);
- return;
- }
-
- if (!m_plugin->load()) {
- m_plugin = 0;
- m_status = PluginStatusCanNotLoadPlugin;
- return;
- }
-
- if (!start()) {
- m_status = PluginStatusCanNotLoadPlugin;
- return;
- }
+ ASSERT(m_isStarted);
+ ASSERT(m_status == PluginStatusLoadedSuccessfully);
if (m_plugin->pluginFuncs()->getvalue) {
PluginView::setCurrentPluginView(this);
@@ -484,22 +451,22 @@ void PluginView::init()
PluginView::setCurrentPluginView(0);
}
-#if PLATFORM(X11)
+#if defined(XP_UNIX)
if (m_needsXEmbed) {
setPlatformWidget(gtk_socket_new());
- gtk_container_add(GTK_CONTAINER(m_parentFrame->view()->hostWindow()->platformWindow()), platformPluginWidget());
+ gtk_container_add(GTK_CONTAINER(m_parentFrame->view()->hostWindow()->platformPageClient()), platformPluginWidget());
g_signal_connect(platformPluginWidget(), "plug_removed", G_CALLBACK(plug_removed_cb), NULL);
} else if (m_isWindowed)
- setPlatformWidget(gtk_xtbin_new(m_parentFrame->view()->hostWindow()->platformWindow()->window, 0));
+ setPlatformWidget(gtk_xtbin_new(m_parentFrame->view()->hostWindow()->platformPageClient()->window, 0));
#else
setPlatformWidget(gtk_socket_new());
- gtk_container_add(GTK_CONTAINER(m_parentFrame->view()->hostWindow()->platformWindow()), platformPluginWidget());
+ gtk_container_add(GTK_CONTAINER(m_parentFrame->view()->hostWindow()->platformPageClient()), platformPluginWidget());
#endif
show();
if (m_isWindowed) {
m_npWindow.type = NPWindowTypeWindow;
-#if PLATFORM(X11)
+#if defined(XP_UNIX)
NPSetWindowCallbackStruct *ws = new NPSetWindowCallbackStruct();
ws->type = 0;
@@ -533,10 +500,18 @@ void PluginView::init()
if (!(m_plugin->quirks().contains(PluginQuirkDeferFirstSetWindowCall)))
updatePluginWidget(); // was: setNPWindowIfNeeded(), but this doesn't produce 0x0 rects at first go
- m_status = PluginStatusLoadedSuccessfully;
+ return true;
+}
+
+void PluginView::platformDestroy()
+{
+}
+
+void PluginView::halt()
+{
}
-void PluginView::platformStart()
+void PluginView::restart()
{
}
diff --git a/WebCore/plugins/mac/PluginPackageMac.cpp b/WebCore/plugins/mac/PluginPackageMac.cpp
index bf6a81b..d242fb8 100644
--- a/WebCore/plugins/mac/PluginPackageMac.cpp
+++ b/WebCore/plugins/mac/PluginPackageMac.cpp
@@ -246,9 +246,6 @@ bool PluginPackage::fetchInfo()
bool PluginPackage::isPluginBlacklisted()
{
- if (name() == "Silverlight Plug-In" || name().startsWith("QuickTime Plug-in"))
- return true;
-
return false;
}
diff --git a/WebCore/plugins/mac/PluginViewMac.cpp b/WebCore/plugins/mac/PluginViewMac.cpp
index 26f9eba..0ab91d1 100644
--- a/WebCore/plugins/mac/PluginViewMac.cpp
+++ b/WebCore/plugins/mac/PluginViewMac.cpp
@@ -75,6 +75,7 @@ using JSC::UString;
#if PLATFORM(QT)
#include <QWidget>
#include <QKeyEvent>
+#include "QWebPageClient.h"
QT_BEGIN_NAMESPACE
#if QT_VERSION < 0x040500
extern Q_GUI_EXPORT WindowPtr qt_mac_window_for(const QWidget* w);
@@ -125,30 +126,10 @@ static inline IntPoint topLevelOffsetFor(PlatformWidget widget)
// --------------- Lifetime management -----------------
-void PluginView::init()
+bool PluginView::platformStart()
{
- LOG(Plugins, "PluginView::init(): Initializing plug-in '%s'", m_plugin->name().utf8().data());
-
- if (m_haveInitialized)
- return;
- m_haveInitialized = true;
-
- if (!m_plugin) {
- ASSERT(m_status == PluginStatusCanNotFindPlugin);
- return;
- }
-
- if (!m_plugin->load()) {
- m_plugin = 0;
- m_status = PluginStatusCanNotLoadPlugin;
- return;
- }
-
- if (!start()) {
- m_status = PluginStatusCanNotLoadPlugin;
- stop(); // Make sure we unregister the plugin
- return;
- }
+ ASSERT(m_isStarted);
+ ASSERT(m_status == PluginStatusLoadedSuccessfully);
if (m_drawingModel == NPDrawingModel(-1)) {
// We default to QuickDraw, even though we don't support it,
@@ -180,8 +161,7 @@ void PluginView::init()
m_status = PluginStatusCanNotLoadPlugin;
LOG(Plugins, "Plug-in '%s' uses unsupported event model %s",
m_plugin->name().utf8().data(), prettyNameForEventModel(m_eventModel));
- stop();
- return;
+ return false;
}
if (getValueStatic(NPNVariable(NPNVsupportsQuickDrawBool + m_drawingModel), &drawingModelSupported) != NPERR_NO_ERROR
@@ -189,38 +169,30 @@ void PluginView::init()
m_status = PluginStatusCanNotLoadPlugin;
LOG(Plugins, "Plug-in '%s' uses unsupported drawing model %s",
m_plugin->name().utf8().data(), prettyNameForDrawingModel(m_drawingModel));
- stop();
- return;
+ return false;
}
- setPlatformPluginWidget(m_parentFrame->view()->hostWindow()->platformWindow());
+#if PLATFORM(QT)
+ if (QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient()) {
+ if (QWidget* window = QWidget::find(client->winId())) {
+ setPlatformPluginWidget(window);
+ }
+ }
+#endif
show();
- m_status = PluginStatusLoadedSuccessfully;
-
// TODO: Implement null timer throttling depending on plugin activation
m_nullEventTimer.set(new Timer<PluginView>(this, &PluginView::nullEventTimerFired));
m_nullEventTimer->startRepeating(0.02);
+
+ return true;
}
-PluginView::~PluginView()
+void PluginView::platformDestroy()
{
- LOG(Plugins, "PluginView::~PluginView()");
-
- stop();
-
- deleteAllValues(m_requests);
-
- freeStringArray(m_paramNames, m_paramCount);
- freeStringArray(m_paramValues, m_paramCount);
-
- m_parentFrame->script()->cleanupScriptObjectsForPlugin(this);
-
- if (m_plugin && !(m_plugin->quirks().contains(PluginQuirkDontUnloadPlugin)))
- m_plugin->unload();
-
- m_window = 0;
+ if (platformPluginWidget())
+ setPlatformPluginWidget(0);
}
// Used before the plugin view has been initialized properly, and as a
@@ -456,6 +428,14 @@ void PluginView::paint(GraphicsContext* context, const IntRect& rect)
setNPWindowIfNeeded();
+ CGContextRef cgContext = m_npCgContext.context;
+ if (!cgContext)
+ return;
+
+ CGContextSaveGState(cgContext);
+ IntPoint offset = frameRect().location();
+ CGContextTranslateCTM(cgContext, offset.x(), offset.y());
+
EventRecord event;
event.what = updateEvt;
event.message = (long unsigned int)m_npCgContext.window;
@@ -464,15 +444,10 @@ void PluginView::paint(GraphicsContext* context, const IntRect& rect)
event.where.v = 0;
event.modifiers = GetCurrentKeyModifiers();
- CGContextRef cg = m_npCgContext.context;
- CGContextSaveGState(cg);
- IntPoint offset = frameRect().location();
- CGContextTranslateCTM(cg, offset.x(), offset.y());
-
if (!dispatchNPEvent(event))
LOG(Events, "PluginView::paint(): Paint event not accepted");
- CGContextRestoreGState(cg);
+ CGContextRestoreGState(cgContext);
}
void PluginView::invalidateRect(const IntRect& rect)
@@ -717,10 +692,13 @@ NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const c
return NPERR_NO_ERROR;
}
-void PluginView::platformStart()
+void PluginView::halt()
{
}
+void PluginView::restart()
+{
+}
} // namespace WebCore
diff --git a/WebCore/plugins/qt/PluginPackageQt.cpp b/WebCore/plugins/qt/PluginPackageQt.cpp
index b9c1656..8119924 100644
--- a/WebCore/plugins/qt/PluginPackageQt.cpp
+++ b/WebCore/plugins/qt/PluginPackageQt.cpp
@@ -63,7 +63,7 @@ bool PluginPackage::fetchInfo()
String s = gm();
Vector<String> types;
s.split(UChar(';'), false, types);
- for (int i = 0; i < types.size(); ++i) {
+ for (unsigned i = 0; i < types.size(); ++i) {
Vector<String> mime;
types[i].split(UChar(':'), true, mime);
if (mime.size() > 0) {
@@ -80,6 +80,16 @@ bool PluginPackage::fetchInfo()
return true;
}
+static NPError staticPluginQuirkRequiresGtkToolKit_NPN_GetValue(NPP instance, NPNVariable variable, void* value)
+{
+ if (variable == NPNVToolkit) {
+ *static_cast<uint32*>(value) = 2;
+ return NPERR_NO_ERROR;
+ }
+
+ return NPN_GetValue(instance, variable, value);
+}
+
bool PluginPackage::load()
{
if (m_isLoaded) {
@@ -111,6 +121,12 @@ bool PluginPackage::load()
initializeBrowserFuncs();
+ if (m_path.contains("npwrapper.")) {
+ // nspluginwrapper relies on the toolkit value to know if glib is available
+ // It does so in NP_Initialize with a null instance, therefore it is done this way:
+ m_browserFuncs.getvalue = staticPluginQuirkRequiresGtkToolKit_NPN_GetValue;
+ }
+
#if defined(XP_UNIX)
npErr = NP_Initialize(&m_browserFuncs, &m_pluginFuncs);
#else
diff --git a/WebCore/plugins/qt/PluginViewQt.cpp b/WebCore/plugins/qt/PluginViewQt.cpp
index a02a8fd..27639e1 100644
--- a/WebCore/plugins/qt/PluginViewQt.cpp
+++ b/WebCore/plugins/qt/PluginViewQt.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
* Copyright (C) 2008 Collabora Ltd. All rights reserved.
+ * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,6 +31,8 @@
#include "Document.h"
#include "DocumentLoader.h"
#include "Element.h"
+#include "FloatPoint.h"
+#include "FocusController.h"
#include "Frame.h"
#include "FrameLoadRequest.h"
#include "FrameLoader.h"
@@ -56,12 +59,21 @@
#include "npruntime_impl.h"
#include "runtime.h"
#include "runtime_root.h"
+#include "QWebPageClient.h"
+#include <QApplication>
+#include <QDesktopWidget>
#include <QKeyEvent>
+#include <QPainter>
#include <QWidget>
#include <QX11Info>
#include <runtime/JSLock.h>
#include <runtime/JSValue.h>
#include <X11/X.h>
+#ifndef QT_NO_XRENDER
+#define Bool int
+#define Status int
+#include <X11/extensions/Xrender.h>
+#endif
using JSC::ExecState;
using JSC::Interpreter;
@@ -79,7 +91,7 @@ using namespace HTMLNames;
void PluginView::updatePluginWidget()
{
- if (!parent() || !m_isWindowed || !platformPluginWidget())
+ if (!parent())
return;
ASSERT(parent()->isFrameView());
@@ -95,6 +107,15 @@ void PluginView::updatePluginWidget()
if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect)
return;
+ if (m_drawable)
+ XFreePixmap(QX11Info::display(), m_drawable);
+
+ if (!m_isWindowed) {
+ m_drawable = XCreatePixmap(QX11Info::display(), QX11Info::appRootWindow(), m_windowRect.width(), m_windowRect.height(),
+ ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth);
+ QApplication::syncX(); // make sure that the server knows about the Drawable
+ }
+
// do not call setNPWindowIfNeeded immediately, will be called on paint()
m_hasPendingGeometryChange = true;
@@ -149,8 +170,67 @@ void PluginView::paint(GraphicsContext* context, const IntRect& rect)
if (context->paintingDisabled())
return;
- if (m_isWindowed && platformPluginWidget())
- setNPWindowIfNeeded();
+ setNPWindowIfNeeded();
+
+ if (m_isWindowed || !m_drawable)
+ return;
+
+ const bool syncX = m_pluginDisplay && m_pluginDisplay != QX11Info::display();
+
+ QPainter* painter = context->platformContext();
+
+ QPixmap qtDrawable = QPixmap::fromX11Pixmap(m_drawable, QPixmap::ExplicitlyShared);
+ const int drawableDepth = ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth;
+ ASSERT(drawableDepth == qtDrawable.depth());
+
+ if (m_isTransparent && drawableDepth != 32) {
+ // Attempt content propagation for drawable with no alpha by copying over from the backing store
+ QPoint offset;
+ QPaintDevice* backingStoreDevice = QPainter::redirected(painter->device(), &offset);
+ offset = -offset; // negating the offset gives us the offset of the view within the backing store pixmap
+
+ const bool hasValidBackingStore = backingStoreDevice && backingStoreDevice->devType() == QInternal::Pixmap;
+ QPixmap* backingStorePixmap = static_cast<QPixmap*>(backingStoreDevice);
+
+ // We cannot grab contents from the backing store when painting on QGraphicsView items
+ // (because backing store contents are already transformed). What we really mean to do
+ // here is to check if we are painting on QWebView, but let's be a little permissive :)
+ QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
+ const bool backingStoreHasUntransformedContents = qobject_cast<QWidget*>(client->pluginParent());
+
+ if (hasValidBackingStore && backingStorePixmap->depth() == drawableDepth
+ && backingStoreHasUntransformedContents) {
+ GC gc = XDefaultGC(QX11Info::display(), QX11Info::appScreen());
+ XCopyArea(QX11Info::display(), backingStorePixmap->handle(), m_drawable, gc,
+ offset.x() + m_windowRect.x() + m_clipRect.x(), offset.y() + m_windowRect.y() + m_clipRect.y(),
+ m_clipRect.width(), m_clipRect.height(), m_clipRect.x(), m_clipRect.y());
+ } else { // no backing store, clean the pixmap because the plugin thinks its transparent
+ QPainter painter(&qtDrawable);
+ painter.fillRect(m_clipRect, Qt::white);
+ }
+
+ if (syncX)
+ QApplication::syncX();
+ }
+
+ XEvent xevent;
+ memset(&xevent, 0, sizeof(XEvent));
+ XGraphicsExposeEvent& exposeEvent = xevent.xgraphicsexpose;
+ exposeEvent.type = GraphicsExpose;
+ exposeEvent.display = QX11Info::display();
+ exposeEvent.drawable = m_drawable;
+ exposeEvent.x = m_clipRect.x();
+ exposeEvent.y = m_clipRect.y();
+ exposeEvent.width = m_clipRect.x() + m_clipRect.width(); // flash bug? it thinks width is the right
+ exposeEvent.height = m_clipRect.y() + m_clipRect.height(); // flash bug? it thinks height is the bottom
+
+ dispatchNPEvent(xevent);
+
+ if (syncX)
+ XSync(m_pluginDisplay, False); // sync changes by plugin
+
+ painter->drawPixmap(frameRect().x() + m_clipRect.x(), frameRect().y() + m_clipRect.y(), qtDrawable,
+ m_clipRect.x(), m_clipRect.y(), m_clipRect.width(), m_clipRect.height());
}
// TODO: Unify across ports.
@@ -163,42 +243,52 @@ bool PluginView::dispatchNPEvent(NPEvent& event)
JSC::JSLock::DropAllLocks dropAllLocks(false);
setCallingPlugin(true);
- bool accepted = m_plugin->pluginFuncs();
+ bool accepted = m_plugin->pluginFuncs()->event(m_instance, &event);
setCallingPlugin(false);
return accepted;
}
-void setSharedXEventFields(XEvent& xEvent, QWidget* hostWindow)
+void setSharedXEventFields(XEvent* xEvent, QWidget* hostWindow)
{
- xEvent.xany.serial = 0; // we are unaware of the last request processed by X Server
- xEvent.xany.send_event = false;
- xEvent.xany.display = hostWindow->x11Info().display();
- // NOTE: event.xany.window doesn't always respond to the .window property of other XEvent's
+ xEvent->xany.serial = 0; // we are unaware of the last request processed by X Server
+ xEvent->xany.send_event = false;
+ xEvent->xany.display = hostWindow->x11Info().display();
+ // NOTE: event->xany.window doesn't always respond to the .window property of other XEvent's
// but does in the case of KeyPress, KeyRelease, ButtonPress, ButtonRelease, and MotionNotify
// events; thus, this is right:
- xEvent.xany.window = hostWindow->window()->handle();
+ xEvent->xany.window = hostWindow->window()->handle();
}
-void setXKeyEventSpecificFields(XEvent& xEvent, KeyboardEvent* event)
+void PluginView::initXEvent(XEvent* xEvent)
+{
+ memset(xEvent, 0, sizeof(XEvent));
+
+ QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
+ QWidget* window = QWidget::find(client->winId());
+ setSharedXEventFields(xEvent, window);
+}
+
+void setXKeyEventSpecificFields(XEvent* xEvent, KeyboardEvent* event)
{
QKeyEvent* qKeyEvent = event->keyEvent()->qtEvent();
- xEvent.xkey.root = QX11Info::appRootWindow();
- xEvent.xkey.subwindow = 0; // we have no child window
- xEvent.xkey.time = event->timeStamp();
- xEvent.xkey.state = qKeyEvent->nativeModifiers();
- xEvent.xkey.keycode = qKeyEvent->nativeScanCode();
- xEvent.xkey.same_screen = true;
+ xEvent->type = (event->type() == eventNames().keydownEvent) ? 2 : 3; // ints as Qt unsets KeyPress and KeyRelease
+ xEvent->xkey.root = QX11Info::appRootWindow();
+ xEvent->xkey.subwindow = 0; // we have no child window
+ xEvent->xkey.time = event->timeStamp();
+ xEvent->xkey.state = qKeyEvent->nativeModifiers();
+ xEvent->xkey.keycode = qKeyEvent->nativeScanCode();
+ xEvent->xkey.same_screen = true;
// NOTE: As the XEvents sent to the plug-in are synthesized and there is not a native window
// corresponding to the plug-in rectangle, some of the members of the XEvent structures are not
// set to their normal Xserver values. e.g. Key events don't have a position.
// source: https://developer.mozilla.org/en/NPEvent
- xEvent.xkey.x = 0;
- xEvent.xkey.y = 0;
- xEvent.xkey.x_root = 0;
- xEvent.xkey.y_root = 0;
+ xEvent->xkey.x = 0;
+ xEvent->xkey.y = 0;
+ xEvent->xkey.x_root = 0;
+ xEvent->xkey.y_root = 0;
}
void PluginView::handleKeyboardEvent(KeyboardEvent* event)
@@ -206,23 +296,147 @@ void PluginView::handleKeyboardEvent(KeyboardEvent* event)
if (m_isWindowed)
return;
- if (event->type() != "keydown" && event->type() != "keyup")
+ if (event->type() != eventNames().keydownEvent && event->type() != eventNames().keyupEvent)
return;
- XEvent npEvent; // On UNIX NPEvent is a typedef for XEvent.
-
- npEvent.type = (event->type() == "keydown") ? 2 : 3; // ints as Qt unsets KeyPress and KeyRelease
- setSharedXEventFields(npEvent, m_parentFrame->view()->hostWindow()->platformWindow());
- setXKeyEventSpecificFields(npEvent, event);
+ XEvent npEvent;
+ initXEvent(&npEvent);
+ setXKeyEventSpecificFields(&npEvent, event);
if (!dispatchNPEvent(npEvent))
event->setDefaultHandled();
}
+static unsigned int inputEventState(MouseEvent* event)
+{
+ unsigned int state = 0;
+ if (event->ctrlKey())
+ state |= ControlMask;
+ if (event->shiftKey())
+ state |= ShiftMask;
+ if (event->altKey())
+ state |= Mod1Mask;
+ if (event->metaKey())
+ state |= Mod4Mask;
+ return state;
+}
+
+static void setXButtonEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos)
+{
+ XButtonEvent& xbutton = xEvent->xbutton;
+ xbutton.type = event->type() == eventNames().mousedownEvent ? ButtonPress : ButtonRelease;
+ xbutton.root = QX11Info::appRootWindow();
+ xbutton.subwindow = 0;
+ xbutton.time = event->timeStamp();
+ xbutton.x = postZoomPos.x();
+ xbutton.y = postZoomPos.y();
+ xbutton.x_root = event->screenX();
+ xbutton.y_root = event->screenY();
+ xbutton.state = inputEventState(event);
+ switch (event->button()) {
+ case MiddleButton:
+ xbutton.button = Button2;
+ break;
+ case RightButton:
+ xbutton.button = Button3;
+ break;
+ case LeftButton:
+ default:
+ xbutton.button = Button1;
+ break;
+ }
+ xbutton.same_screen = true;
+}
+
+static void setXMotionEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos)
+{
+ XMotionEvent& xmotion = xEvent->xmotion;
+ xmotion.type = MotionNotify;
+ xmotion.root = QX11Info::appRootWindow();
+ xmotion.subwindow = 0;
+ xmotion.time = event->timeStamp();
+ xmotion.x = postZoomPos.x();
+ xmotion.y = postZoomPos.y();
+ xmotion.x_root = event->screenX();
+ xmotion.y_root = event->screenY();
+ xmotion.state = inputEventState(event);
+ xmotion.is_hint = NotifyNormal;
+ xmotion.same_screen = true;
+}
+
+static void setXCrossingEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos)
+{
+ XCrossingEvent& xcrossing = xEvent->xcrossing;
+ xcrossing.type = event->type() == eventNames().mouseoverEvent ? EnterNotify : LeaveNotify;
+ xcrossing.root = QX11Info::appRootWindow();
+ xcrossing.subwindow = 0;
+ xcrossing.time = event->timeStamp();
+ xcrossing.x = postZoomPos.y();
+ xcrossing.y = postZoomPos.x();
+ xcrossing.x_root = event->screenX();
+ xcrossing.y_root = event->screenY();
+ xcrossing.state = inputEventState(event);
+ xcrossing.mode = NotifyNormal;
+ xcrossing.detail = NotifyDetailNone;
+ xcrossing.same_screen = true;
+ xcrossing.focus = false;
+}
+
void PluginView::handleMouseEvent(MouseEvent* event)
{
if (m_isWindowed)
return;
+
+ if (event->type() == eventNames().mousedownEvent) {
+ // Give focus to the plugin on click
+ if (Page* page = m_parentFrame->page())
+ page->focusController()->setActive(true);
+
+ focusPluginElement();
+ }
+
+ XEvent npEvent;
+ initXEvent(&npEvent);
+
+ IntPoint postZoomPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(event->absoluteLocation()));
+
+ if (event->type() == eventNames().mousedownEvent || event->type() == eventNames().mouseupEvent)
+ setXButtonEventSpecificFields(&npEvent, event, postZoomPos);
+ else if (event->type() == eventNames().mousemoveEvent)
+ setXMotionEventSpecificFields(&npEvent, event, postZoomPos);
+ else if (event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mouseoverEvent)
+ setXCrossingEventSpecificFields(&npEvent, event, postZoomPos);
+ else
+ return;
+
+ if (!dispatchNPEvent(npEvent))
+ event->setDefaultHandled();
+}
+
+void PluginView::handleFocusInEvent()
+{
+ XEvent npEvent;
+ initXEvent(&npEvent);
+
+ XFocusChangeEvent& event = npEvent.xfocus;
+ event.type = 9; /* int as Qt unsets FocusIn */
+ event.mode = NotifyNormal;
+ event.detail = NotifyDetailNone;
+
+ dispatchNPEvent(npEvent);
+}
+
+void PluginView::handleFocusOutEvent()
+{
+ XEvent npEvent;
+ initXEvent(&npEvent);
+
+ XFocusChangeEvent& event = npEvent.xfocus;
+ event.type = 10; /* int as Qt unsets FocusOut */
+ event.mode = NotifyNormal;
+ event.detail = NotifyDetailNone;
+
+ dispatchNPEvent(npEvent);
}
void PluginView::setParent(ScrollView* parent)
@@ -235,7 +449,8 @@ void PluginView::setParent(ScrollView* parent)
void PluginView::setNPWindowRect(const IntRect&)
{
- // Ignored as we don't want to move immediately.
+ if (!m_isWindowed)
+ setNPWindowIfNeeded();
}
void PluginView::setNPWindowIfNeeded()
@@ -251,28 +466,38 @@ void PluginView::setNPWindowIfNeeded()
return;
m_hasPendingGeometryChange = false;
- ASSERT(platformPluginWidget());
- platformPluginWidget()->setGeometry(m_windowRect);
- // if setMask is set with an empty QRegion, no clipping will
- // be performed, so in that case we hide the plugin view
- platformPluginWidget()->setVisible(!m_clipRect.isEmpty());
- platformPluginWidget()->setMask(QRegion(m_clipRect));
+ if (m_isWindowed) {
+ ASSERT(platformPluginWidget());
+ platformPluginWidget()->setGeometry(m_windowRect);
+ // if setMask is set with an empty QRegion, no clipping will
+ // be performed, so in that case we hide the plugin view
+ platformPluginWidget()->setVisible(!m_clipRect.isEmpty());
+ platformPluginWidget()->setMask(QRegion(m_clipRect));
+
+ m_npWindow.x = m_windowRect.x();
+ m_npWindow.y = m_windowRect.y();
+
+ m_npWindow.clipRect.left = m_clipRect.x();
+ m_npWindow.clipRect.top = m_clipRect.y();
+ m_npWindow.clipRect.right = m_clipRect.width();
+ m_npWindow.clipRect.bottom = m_clipRect.height();
+ } else {
+ m_npWindow.x = 0;
+ m_npWindow.y = 0;
+
+ m_npWindow.clipRect.left = 0;
+ m_npWindow.clipRect.top = 0;
+ m_npWindow.clipRect.right = 0;
+ m_npWindow.clipRect.bottom = 0;
+ }
// FLASH WORKAROUND: Only set initially. Multiple calls to
- // setNPWindow() cause the plugin to crash.
- if (m_npWindow.width == -1 || m_npWindow.height == -1) {
+ // setNPWindow() cause the plugin to crash in windowed mode.
+ if (!m_isWindowed || m_npWindow.width == -1 || m_npWindow.height == -1) {
m_npWindow.width = m_windowRect.width();
m_npWindow.height = m_windowRect.height();
}
- m_npWindow.x = m_windowRect.x();
- m_npWindow.y = m_windowRect.y();
-
- m_npWindow.clipRect.left = m_clipRect.x();
- m_npWindow.clipRect.top = m_clipRect.y();
- m_npWindow.clipRect.right = m_clipRect.width();
- m_npWindow.clipRect.bottom = m_clipRect.height();
-
PluginView::setCurrentPluginView(this);
JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
setCallingPlugin(true);
@@ -337,6 +562,10 @@ NPError PluginView::getValueStatic(NPNVariable variable, void* value)
*static_cast<NPBool*>(value) = true;
return NPERR_NO_ERROR;
+ case NPNVSupportsWindowless:
+ *static_cast<NPBool*>(value) = true;
+ return NPERR_NO_ERROR;
+
default:
return NPERR_GENERIC_ERROR;
}
@@ -350,8 +579,11 @@ NPError PluginView::getValue(NPNVariable variable, void* value)
case NPNVxDisplay:
if (platformPluginWidget())
*(void **)value = platformPluginWidget()->x11Info().display();
- else
- *(void **)value = m_parentFrame->view()->hostWindow()->platformWindow()->x11Info().display();
+ else {
+ QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
+ QWidget* window = QWidget::find(client->winId());
+ *(void **)value = window->x11Info().display();
+ }
return NPERR_NO_ERROR;
case NPNVxtAppContext:
@@ -396,7 +628,7 @@ NPError PluginView::getValue(NPNVariable variable, void* value)
case NPNVnetscapeWindow: {
void* w = reinterpret_cast<void*>(value);
- *((XID *)w) = m_parentFrame->view()->hostWindow()->platformWindow()->winId();
+ *((XID *)w) = m_parentFrame->view()->hostWindow()->platformPageClient()->winId();
return NPERR_NO_ERROR;
}
@@ -413,7 +645,7 @@ NPError PluginView::getValue(NPNVariable variable, void* value)
void PluginView::invalidateRect(const IntRect& rect)
{
- if (platformWidget()) {
+ if (m_isWindowed) {
platformWidget()->update(rect);
return;
}
@@ -423,59 +655,94 @@ void PluginView::invalidateRect(const IntRect& rect)
void PluginView::invalidateRect(NPRect* rect)
{
- notImplemented();
+ if (!rect) {
+ invalidate();
+ return;
+ }
+ IntRect r(rect->left, rect->top, rect->right + rect->left, rect->bottom + rect->top);
+ invalidateWindowlessPluginRect(r);
}
void PluginView::invalidateRegion(NPRegion region)
{
- notImplemented();
+ invalidate();
}
void PluginView::forceRedraw()
{
- notImplemented();
+ invalidate();
}
-PluginView::~PluginView()
+static Display *getPluginDisplay()
{
- stop();
-
- deleteAllValues(m_requests);
-
- freeStringArray(m_paramNames, m_paramCount);
- freeStringArray(m_paramValues, m_paramCount);
-
- m_parentFrame->script()->cleanupScriptObjectsForPlugin(this);
-
- if (m_plugin && !(m_plugin->quirks().contains(PluginQuirkDontUnloadPlugin)))
- m_plugin->unload();
-
- delete platformPluginWidget();
+ // The plugin toolkit might run using a different X connection. At the moment, we only
+ // support gdk based plugins (like flash) that use a different X connection.
+ // The code below has the same effect as this one:
+ // Display *gdkDisplay = gdk_x11_display_get_xdisplay(gdk_display_get_default());
+ QLibrary library("libgdk-x11-2.0");
+ if (!library.load())
+ return 0;
+
+ typedef void *(*gdk_display_get_default_ptr)();
+ gdk_display_get_default_ptr gdk_display_get_default = (gdk_display_get_default_ptr)library.resolve("gdk_display_get_default");
+ if (!gdk_display_get_default)
+ return 0;
+
+ typedef void *(*gdk_x11_display_get_xdisplay_ptr)(void *);
+ gdk_x11_display_get_xdisplay_ptr gdk_x11_display_get_xdisplay = (gdk_x11_display_get_xdisplay_ptr)library.resolve("gdk_x11_display_get_xdisplay");
+ if (!gdk_x11_display_get_xdisplay)
+ return 0;
+
+ return (Display*)gdk_x11_display_get_xdisplay(gdk_display_get_default());
}
-void PluginView::init()
+static void getVisualAndColormap(int depth, Visual **visual, Colormap *colormap)
{
- if (m_haveInitialized)
- return;
- m_haveInitialized = true;
+ *visual = 0;
+ *colormap = 0;
- m_hasPendingGeometryChange = false;
+#ifndef QT_NO_XRENDER
+ static const bool useXRender = qgetenv("QT_X11_NO_XRENDER").isNull(); // Should also check for XRender >= 0.5
+#else
+ static const bool useXRender = false;
+#endif
- if (!m_plugin) {
- ASSERT(m_status == PluginStatusCanNotFindPlugin);
+ if (!useXRender && depth == 32)
return;
- }
- if (!m_plugin->load()) {
- m_plugin = 0;
- m_status = PluginStatusCanNotLoadPlugin;
- return;
- }
+ int nvi;
+ XVisualInfo templ;
+ templ.screen = QX11Info::appScreen();
+ templ.depth = depth;
+ templ.c_class = TrueColor;
+ XVisualInfo* xvi = XGetVisualInfo(QX11Info::display(), VisualScreenMask | VisualDepthMask | VisualClassMask, &templ, &nvi);
- if (!start()) {
- m_status = PluginStatusCanNotLoadPlugin;
+ if (!xvi)
return;
- }
+
+#ifndef QT_NO_XRENDER
+ if (depth == 32) {
+ for (int idx = 0; idx < nvi; ++idx) {
+ XRenderPictFormat* format = XRenderFindVisualFormat(QX11Info::display(), xvi[idx].visual);
+ if (format->type == PictTypeDirect && format->direct.alphaMask) {
+ *visual = xvi[idx].visual;
+ break;
+ }
+ }
+ } else
+#endif // QT_NO_XRENDER
+ *visual = xvi[0].visual;
+
+ XFree(xvi);
+
+ if (*visual)
+ *colormap = XCreateColormap(QX11Info::display(), QX11Info::appRootWindow(), *visual, AllocNone);
+}
+
+bool PluginView::platformStart()
+{
+ ASSERT(m_isStarted);
+ ASSERT(m_status == PluginStatusLoadedSuccessfully);
if (m_plugin->pluginFuncs()->getvalue) {
PluginView::setCurrentPluginView(this);
@@ -486,41 +753,92 @@ void PluginView::init()
PluginView::setCurrentPluginView(0);
}
- if (m_needsXEmbed) {
- setPlatformWidget(new PluginContainerQt(this, m_parentFrame->view()->hostWindow()->platformWindow()));
+ if (m_isWindowed) {
+ if (m_needsXEmbed) {
+ QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
+ setPlatformWidget(new PluginContainerQt(this, QWidget::find(client->winId())));
+ // sync our XEmbed container window creation before sending the xid to plugins.
+ QApplication::syncX();
+ } else {
+ notImplemented();
+ m_status = PluginStatusCanNotLoadPlugin;
+ return false;
+ }
} else {
- notImplemented();
- m_status = PluginStatusCanNotLoadPlugin;
- return;
+ setPlatformWidget(0);
+ m_pluginDisplay = getPluginDisplay();
}
- show();
- NPSetWindowCallbackStruct *wsi = new NPSetWindowCallbackStruct();
+ show();
+ NPSetWindowCallbackStruct* wsi = new NPSetWindowCallbackStruct();
wsi->type = 0;
- wsi->display = platformPluginWidget()->x11Info().display();
- wsi->visual = (Visual*)platformPluginWidget()->x11Info().visual();
- wsi->depth = platformPluginWidget()->x11Info().depth();
- wsi->colormap = platformPluginWidget()->x11Info().colormap();
- m_npWindow.ws_info = wsi;
+ if (m_isWindowed) {
+ const QX11Info* x11Info = &platformPluginWidget()->x11Info();
+
+ wsi->display = x11Info->display();
+ wsi->visual = (Visual*)x11Info->visual();
+ wsi->depth = x11Info->depth();
+ wsi->colormap = x11Info->colormap();
+
+ m_npWindow.type = NPWindowTypeWindow;
+ m_npWindow.window = (void*)platformPluginWidget()->winId();
+ m_npWindow.width = -1;
+ m_npWindow.height = -1;
+ } else {
+ const QX11Info* x11Info = &QApplication::desktop()->x11Info();
+
+ if (x11Info->depth() == 32 || !m_plugin->quirks().contains(PluginQuirkRequiresDefaultScreenDepth)) {
+ getVisualAndColormap(32, &m_visual, &m_colormap);
+ wsi->depth = 32;
+ }
+
+ if (!m_visual) {
+ getVisualAndColormap(x11Info->depth(), &m_visual, &m_colormap);
+ wsi->depth = x11Info->depth();
+ }
+
+ wsi->display = x11Info->display();
+ wsi->visual = m_visual;
+ wsi->colormap = m_colormap;
- m_npWindow.type = NPWindowTypeWindow;
- m_npWindow.window = (void*)platformPluginWidget()->winId();
- m_npWindow.width = -1;
- m_npWindow.height = -1;
+ m_npWindow.type = NPWindowTypeDrawable;
+ m_npWindow.window = 0; // Not used?
+ m_npWindow.x = 0;
+ m_npWindow.y = 0;
+ m_npWindow.width = -1;
+ m_npWindow.height = -1;
+ }
+
+ m_npWindow.ws_info = wsi;
if (!(m_plugin->quirks().contains(PluginQuirkDeferFirstSetWindowCall))) {
updatePluginWidget();
setNPWindowIfNeeded();
}
- m_status = PluginStatusLoadedSuccessfully;
+ return true;
}
-void PluginView::platformStart()
+void PluginView::platformDestroy()
+{
+ if (platformPluginWidget())
+ delete platformPluginWidget();
+
+ if (m_drawable)
+ XFreePixmap(QX11Info::display(), m_drawable);
+
+ if (m_colormap)
+ XFreeColormap(QX11Info::display(), m_colormap);
+}
+
+void PluginView::halt()
{
}
+void PluginView::restart()
+{
+}
} // namespace WebCore
diff --git a/WebCore/plugins/win/PaintHooks.asm b/WebCore/plugins/win/PaintHooks.asm
new file mode 100644
index 0000000..1508813
--- /dev/null
+++ b/WebCore/plugins/win/PaintHooks.asm
@@ -0,0 +1,50 @@
+;/*
+; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Library General Public
+; License as published by the Free Software Foundation; either
+; version 2 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Library General Public License for more details.
+;
+; You should have received a copy of the GNU Library General Public License
+; along with this library; see the file COPYING.LIB. If not, write to
+; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+; Boston, MA 02110-1301, USA.
+;*/
+
+;HDC __stdcall _HBeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint);
+
+PUBLIC _HBeginPaint
+
+_TEXT SEGMENT
+
+_HBeginPaint PROC
+ mov r10,rcx
+ mov eax,1017h
+ syscall
+ ret
+_HBeginPaint ENDP
+
+_TEXT ENDS
+
+;BOOL __stdcall _HEndPaint(HWND hWnd, const PAINTSTRUCT* lpPaint);
+
+PUBLIC _HEndPaint
+
+_TEXT SEGMENT
+
+_HEndPaint PROC
+ mov r10,rcx
+ mov eax,1019h
+ syscall
+ ret
+_HEndPaint ENDP
+
+_TEXT ENDS
+
+END
diff --git a/WebCore/plugins/win/PluginViewWin.cpp b/WebCore/plugins/win/PluginViewWin.cpp
index 0da4402..ccbf6f8 100644
--- a/WebCore/plugins/win/PluginViewWin.cpp
+++ b/WebCore/plugins/win/PluginViewWin.cpp
@@ -29,6 +29,7 @@
#include "PluginView.h"
+#include "BitmapImage.h"
#include "Document.h"
#include "DocumentLoader.h"
#include "Element.h"
@@ -52,6 +53,7 @@
#include "PluginMessageThrottlerWin.h"
#include "PluginPackage.h"
#include "PluginMainThreadScheduler.h"
+#include "RenderWidget.h"
#include "JSDOMBinding.h"
#include "ScriptController.h"
#include "PluginDatabase.h"
@@ -74,17 +76,17 @@
#endif
#if PLATFORM(QT)
-#include <QWidget.h>
+#include "QWebPageClient.h"
#endif
-static inline HWND windowHandleForPlatformWidget(PlatformWidget widget)
+static inline HWND windowHandleForPageClient(PlatformPageClient client)
{
#if PLATFORM(QT)
- if (!widget)
+ if (!client)
return 0;
- return widget->winId();
+ return client->winId();
#else
- return widget;
+ return client;
#endif
}
@@ -115,6 +117,14 @@ static BYTE* beginPaint;
static unsigned endPaintSysCall;
static BYTE* endPaint;
+typedef HDC (WINAPI *PtrBeginPaint)(HWND, PAINTSTRUCT*);
+typedef BOOL (WINAPI *PtrEndPaint)(HWND, const PAINTSTRUCT*);
+
+#if PLATFORM(WIN_OS) && PLATFORM(X86_64) && COMPILER(MSVC)
+extern "C" HDC __stdcall _HBeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint);
+extern "C" BOOL __stdcall _HEndPaint(HWND hWnd, const PAINTSTRUCT* lpPaint);
+#endif
+
HDC WINAPI PluginView::hookedBeginPaint(HWND hWnd, PAINTSTRUCT* lpPaint)
{
PluginView* pluginView = reinterpret_cast<PluginView*>(GetProp(hWnd, kWebPluginViewProperty));
@@ -137,12 +147,14 @@ HDC WINAPI PluginView::hookedBeginPaint(HWND hWnd, PAINTSTRUCT* lpPaint)
: "memory"
);
return result;
-#else
+#elif defined(_M_IX86)
// Call through to the original BeginPaint.
__asm mov eax, beginPaintSysCall
__asm push lpPaint
__asm push hWnd
__asm call beginPaint
+#else
+ return _HBeginPaint(hWnd, lpPaint);
#endif
}
@@ -164,12 +176,14 @@ BOOL WINAPI PluginView::hookedEndPaint(HWND hWnd, const PAINTSTRUCT* lpPaint)
: "a" (endPaintSysCall), "g" (lpPaint), "g" (hWnd), "m" (*endPaint)
);
return result;
-#else
+#elif defined (_M_IX86)
// Call through to the original EndPaint.
__asm mov eax, endPaintSysCall
__asm push lpPaint
__asm push hWnd
__asm call endPaint
+#else
+ return _HEndPaint(hWnd, lpPaint);
#endif
}
@@ -182,6 +196,7 @@ static void hook(const char* module, const char* proc, unsigned& sysCallID, BYTE
pProc = reinterpret_cast<BYTE*>(reinterpret_cast<ptrdiff_t>(GetProcAddress(hMod, proc)));
+#if COMPILER(GCC) || defined(_M_IX86)
if (pProc[0] != 0xB8)
return;
@@ -197,6 +212,35 @@ static void hook(const char* module, const char* proc, unsigned& sysCallID, BYTE
*reinterpret_cast<unsigned*>(pProc + 1) = reinterpret_cast<intptr_t>(pNewProc) - reinterpret_cast<intptr_t>(pProc + 5);
pProc += 5;
+#else
+ /* Disassembly of BeginPaint()
+ 00000000779FC5B0 4C 8B D1 mov r10,rcx
+ 00000000779FC5B3 B8 17 10 00 00 mov eax,1017h
+ 00000000779FC5B8 0F 05 syscall
+ 00000000779FC5BA C3 ret
+ 00000000779FC5BB 90 nop
+ 00000000779FC5BC 90 nop
+ 00000000779FC5BD 90 nop
+ 00000000779FC5BE 90 nop
+ 00000000779FC5BF 90 nop
+ 00000000779FC5C0 90 nop
+ 00000000779FC5C1 90 nop
+ 00000000779FC5C2 90 nop
+ 00000000779FC5C3 90 nop
+ */
+ // Check for the signature as in the above disassembly
+ DWORD guard = 0xB8D18B4C;
+ if (*reinterpret_cast<DWORD*>(pProc) != guard)
+ return;
+
+ DWORD flOldProtect;
+ VirtualProtect(pProc, 12, PAGE_EXECUTE_READWRITE, & flOldProtect);
+ pProc[0] = 0x48; // mov rax, this
+ pProc[1] = 0xb8;
+ *(__int64*)(pProc+2) = (__int64)pNewProc;
+ pProc[10] = 0xff; // jmp rax
+ pProc[11] = 0xe0;
+#endif
}
static void setUpOffscreenPaintingHooks(HDC (WINAPI*hookedBeginPaint)(HWND, PAINTSTRUCT*), BOOL (WINAPI*hookedEndPaint)(HWND, const PAINTSTRUCT*))
@@ -838,7 +882,7 @@ NPError PluginView::getValue(NPNVariable variable, void* value)
case NPNVnetscapeWindow: {
HWND* w = reinterpret_cast<HWND*>(value);
- *w = windowHandleForPlatformWidget(parent() ? parent()->hostWindow()->platformWindow() : 0);
+ *w = windowHandleForPageClient(parent() ? parent()->hostWindow()->platformPageClient() : 0);
return NPERR_NO_ERROR;
}
@@ -910,55 +954,10 @@ void PluginView::forceRedraw()
if (m_isWindowed)
::UpdateWindow(platformPluginWidget());
else
- ::UpdateWindow(windowHandleForPlatformWidget(parent() ? parent()->hostWindow()->platformWindow() : 0));
-}
-
-PluginView::~PluginView()
-{
- removeFromUnstartedListIfNecessary();
-
- stop();
-
- deleteAllValues(m_requests);
-
- freeStringArray(m_paramNames, m_paramCount);
- freeStringArray(m_paramValues, m_paramCount);
-
- if (platformPluginWidget())
- DestroyWindow(platformPluginWidget());
-
- m_parentFrame->script()->cleanupScriptObjectsForPlugin(this);
-
- if (m_plugin && !m_plugin->quirks().contains(PluginQuirkDontUnloadPlugin))
- m_plugin->unload();
+ ::UpdateWindow(windowHandleForPageClient(parent() ? parent()->hostWindow()->platformPageClient() : 0));
}
-void PluginView::init()
-{
- if (m_haveInitialized)
- return;
- m_haveInitialized = true;
-
- if (!m_plugin) {
- ASSERT(m_status == PluginStatusCanNotFindPlugin);
- return;
- }
-
- if (!m_plugin->load()) {
- m_plugin = 0;
- m_status = PluginStatusCanNotLoadPlugin;
- return;
- }
-
- if (!startOrAddToUnstartedList()) {
- m_status = PluginStatusCanNotLoadPlugin;
- return;
- }
-
- m_status = PluginStatusLoadedSuccessfully;
-}
-
-void PluginView::platformStart()
+bool PluginView::platformStart()
{
ASSERT(m_isStarted);
ASSERT(m_status == PluginStatusLoadedSuccessfully);
@@ -973,7 +972,7 @@ void PluginView::platformStart()
if (isSelfVisible())
flags |= WS_VISIBLE;
- HWND parentWindowHandle = windowHandleForPlatformWidget(m_parentFrame->view()->hostWindow()->platformWindow());
+ HWND parentWindowHandle = windowHandleForPageClient(m_parentFrame->view()->hostWindow()->platformPageClient());
HWND window = ::CreateWindowEx(0, kWebPluginViewdowClassName, 0, flags,
0, 0, 0, 0, parentWindowHandle, 0, Page::instanceHandle(), 0);
@@ -1005,6 +1004,40 @@ void PluginView::platformStart()
if (!m_plugin->quirks().contains(PluginQuirkDeferFirstSetWindowCall))
setNPWindowRect(frameRect());
+
+ return true;
+}
+
+void PluginView::platformDestroy()
+{
+ if (!platformPluginWidget())
+ return;
+
+ DestroyWindow(platformPluginWidget());
+ setPlatformPluginWidget(0);
+}
+
+void PluginView::halt()
+{
+#if !PLATFORM(QT)
+ // Show a screenshot of the plug-in.
+ OwnPtr<HBITMAP> nodeImage(m_parentFrame->nodeImage(m_element));
+ toRenderWidget(m_element->renderer())->showSubstituteImage(BitmapImage::create(nodeImage.get()));
+#endif
+
+ stop();
+ platformDestroy();
+}
+
+void PluginView::restart()
+{
+ ASSERT(!m_isStarted);
+
+ // Clear any substitute image.
+ toRenderWidget(m_element->renderer())->showSubstituteImage(0);
+
+ m_haveUpdatedPluginWidget = false;
+ start();
}
} // namespace WebCore