diff options
Diffstat (limited to 'WebCore/plugins')
-rw-r--r-- | WebCore/plugins/PluginDatabase.cpp | 16 | ||||
-rw-r--r-- | WebCore/plugins/PluginDatabase.h | 9 | ||||
-rw-r--r-- | WebCore/plugins/PluginDatabaseClient.h | 42 | ||||
-rw-r--r-- | WebCore/plugins/PluginPackage.cpp | 1 | ||||
-rw-r--r-- | WebCore/plugins/PluginQuirkSet.h | 1 | ||||
-rw-r--r-- | WebCore/plugins/PluginView.cpp | 182 | ||||
-rw-r--r-- | WebCore/plugins/PluginView.h | 29 | ||||
-rw-r--r-- | WebCore/plugins/PluginViewNone.cpp | 13 | ||||
-rw-r--r-- | WebCore/plugins/android/PluginViewAndroid.cpp | 76 | ||||
-rw-r--r-- | WebCore/plugins/gtk/PluginViewGtk.cpp | 83 | ||||
-rw-r--r-- | WebCore/plugins/mac/PluginPackageMac.cpp | 3 | ||||
-rw-r--r-- | WebCore/plugins/mac/PluginViewMac.cpp | 84 | ||||
-rw-r--r-- | WebCore/plugins/qt/PluginPackageQt.cpp | 18 | ||||
-rw-r--r-- | WebCore/plugins/qt/PluginViewQt.cpp | 516 | ||||
-rw-r--r-- | WebCore/plugins/win/PaintHooks.asm | 50 | ||||
-rw-r--r-- | WebCore/plugins/win/PluginViewWin.cpp | 145 |
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 |