diff options
Diffstat (limited to 'src/3rdparty/webkit/WebCore/plugins')
25 files changed, 2043 insertions, 568 deletions
diff --git a/src/3rdparty/webkit/WebCore/plugins/PluginDataNone.cpp b/src/3rdparty/webkit/WebCore/plugins/PluginDataNone.cpp index 28e39673e..3b98383cc 100644 --- a/src/3rdparty/webkit/WebCore/plugins/PluginDataNone.cpp +++ b/src/3rdparty/webkit/WebCore/plugins/PluginDataNone.cpp @@ -27,18 +27,14 @@ #include "config.h" #include "PluginData.h" -#include "NotImplemented.h" - namespace WebCore { void PluginData::initPlugins() { - notImplemented(); } void PluginData::refresh() { - notImplemented(); } }; diff --git a/src/3rdparty/webkit/WebCore/plugins/PluginDatabase.cpp b/src/3rdparty/webkit/WebCore/plugins/PluginDatabase.cpp index de1c298e0..ea8e4adea 100644 --- a/src/3rdparty/webkit/WebCore/plugins/PluginDatabase.cpp +++ b/src/3rdparty/webkit/WebCore/plugins/PluginDatabase.cpp @@ -21,7 +21,7 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" @@ -29,11 +29,19 @@ #include "Frame.h" #include "KURL.h" +#include "PluginDatabaseClient.h" #include "PluginPackage.h" #include <stdlib.h> namespace WebCore { +typedef HashMap<String, RefPtr<PluginPackage> > PluginPackageByNameMap; + +PluginDatabase::PluginDatabase() + : m_client(0) +{ +} + PluginDatabase* PluginDatabase::installedPlugins(bool populate) { static PluginDatabase* plugins = 0; @@ -109,9 +117,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. @@ -126,10 +136,10 @@ bool PluginDatabase::refresh() PluginSet::const_iterator end = m_plugins.end(); for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) { // Get MIME types + MIMEToDescriptionsMap::const_iterator map_it = (*it)->mimeToDescriptions().begin(); MIMEToDescriptionsMap::const_iterator map_end = (*it)->mimeToDescriptions().end(); - for (MIMEToDescriptionsMap::const_iterator map_it = (*it)->mimeToDescriptions().begin(); map_it != map_end; ++map_it) { + for (; map_it != map_end; ++map_it) m_registeredMIMETypes.add(map_it->first); - } } return true; @@ -161,12 +171,23 @@ PluginPackage* PluginDatabase::pluginForMIMEType(const String& mimeType) String key = mimeType.lower(); PluginSet::const_iterator end = m_plugins.end(); + PluginPackage* preferredPlugin = m_preferredPlugins.get(key).get(); + if (preferredPlugin + && preferredPlugin->isEnabled() + && preferredPlugin->mimeToDescriptions().contains(key)) { + return preferredPlugin; + } Vector<PluginPackage*, 2> pluginChoices; for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) { - if ((*it)->mimeToDescriptions().contains(key)) - pluginChoices.append((*it).get()); + PluginPackage* plugin = (*it).get(); + + if (!plugin->isEnabled()) + continue; + + if (plugin->mimeToDescriptions().contains(key)) + pluginChoices.append(plugin); } if (pluginChoices.isEmpty()) @@ -188,16 +209,25 @@ String PluginDatabase::MIMETypeForExtension(const String& extension) const HashMap<PluginPackage*, String> mimeTypeForPlugin; for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) { + if (!(*it)->isEnabled()) + continue; + MIMEToExtensionsMap::const_iterator mime_end = (*it)->mimeToExtensions().end(); for (MIMEToExtensionsMap::const_iterator mime_it = (*it)->mimeToExtensions().begin(); mime_it != mime_end; ++mime_it) { + mimeType = mime_it->first; + PluginPackage* preferredPlugin = m_preferredPlugins.get(mimeType).get(); const Vector<String>& extensions = mime_it->second; bool foundMapping = false; for (unsigned i = 0; i < extensions.size(); i++) { if (equalIgnoringCase(extensions[i], extension)) { PluginPackage* plugin = (*it).get(); + + if (preferredPlugin && PluginPackage::equal(*plugin, *preferredPlugin)) + return mimeType; + pluginChoices.append(plugin); - mimeTypeForPlugin.add(plugin, mime_it->first); + mimeTypeForPlugin.add(plugin, mimeType); foundMapping = true; break; } @@ -219,7 +249,7 @@ PluginPackage* PluginDatabase::findPlugin(const KURL& url, String& mimeType) { PluginPackage* plugin = pluginForMIMEType(mimeType); String filename = url.string(); - + if (!plugin) { String filename = url.lastPathComponent(); if (!filename.endsWith("/")) { @@ -233,12 +263,18 @@ PluginPackage* PluginDatabase::findPlugin(const KURL& url, String& mimeType) } } - // FIXME: if no plugin could be found, query Windows for the mime type + // FIXME: if no plugin could be found, query Windows for the mime type // corresponding to the extension. return plugin; } +void PluginDatabase::setPreferredPluginForMIMEType(const String& mimeType, PluginPackage* plugin) +{ + if (!plugin || plugin->mimeToExtensions().contains(mimeType)) + m_preferredPlugins.set(mimeType.lower(), plugin); +} + void PluginDatabase::getDeletedPlugins(PluginSet& plugins) const { PluginSet::const_iterator end = m_plugins.end(); @@ -263,6 +299,14 @@ bool PluginDatabase::add(PassRefPtr<PluginPackage> prpPackage) void PluginDatabase::remove(PluginPackage* package) { + MIMEToExtensionsMap::const_iterator it = package->mimeToExtensions().begin(); + MIMEToExtensionsMap::const_iterator end = package->mimeToExtensions().end(); + for ( ; it != end; ++it) { + PluginPackageByNameMap::iterator packageInMap = m_preferredPlugins.find(it->first); + if (packageInMap != m_preferredPlugins.end() && packageInMap->second == package) + m_preferredPlugins.remove(packageInMap); + } + m_plugins.remove(package); m_pluginsByPath.remove(package->path()); } @@ -273,9 +317,10 @@ void PluginDatabase::clear() m_pluginsByPath.clear(); m_pluginPathsWithTimes.clear(); m_registeredMIMETypes.clear(); + m_preferredPlugins.clear(); } -#if !PLATFORM(WIN_OS) || PLATFORM(WX) +#if (!PLATFORM(WINCE)) && (!PLATFORM(SYMBIAN)) && (!PLATFORM(WIN_OS) || PLATFORM(WX) || !ENABLE(NETSCAPE_PLUGIN_API)) // For Safari/Win the following three methods are implemented // in PluginDatabaseWin.cpp, but if we can use WebCore constructs // for the logic we should perhaps move it here under XP_WIN? @@ -310,6 +355,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"); @@ -333,7 +380,7 @@ Vector<String> PluginDatabase::defaultPluginDirectories() // Add paths specific to each port #if PLATFORM(QT) Vector<String> qtPaths; - String qtPath(getenv("QTWEBKIT_PLUGIN_PATH")); + String qtPath(qgetenv("QTWEBKIT_PLUGIN_PATH").constData()); qtPath.split(UChar(':'), /* allowEmptyEntries */ false, qtPaths); paths.append(qtPaths); #endif @@ -381,6 +428,6 @@ void PluginDatabase::getPluginPathsInDirectories(HashSet<String>& paths) const } } -#endif // !PLATFORM(WIN_OS) +#endif // !PLATFORM(SYMBIAN) && !PLATFORM(WIN_OS) } diff --git a/src/3rdparty/webkit/WebCore/plugins/PluginDatabase.h b/src/3rdparty/webkit/WebCore/plugins/PluginDatabase.h index b8d2bfe5a..fdc933067 100644 --- a/src/3rdparty/webkit/WebCore/plugins/PluginDatabase.h +++ b/src/3rdparty/webkit/WebCore/plugins/PluginDatabase.h @@ -22,7 +22,7 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef PluginDatabase_H @@ -32,20 +32,23 @@ #include "PluginPackage.h" #include "StringHash.h" -#include <wtf/Vector.h> #include <wtf/HashSet.h> +#include <wtf/Vector.h> namespace WebCore { class Element; 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 @@ -63,6 +66,8 @@ namespace WebCore { static int preferredPluginCompare(const void*, const void*); PluginPackage* findPlugin(const KURL&, String& mimeType); + PluginPackage* pluginForMIMEType(const String& mimeType); + void setPreferredPluginForMIMEType(const String& mimeType, PluginPackage* plugin); void setPluginDirectories(const Vector<String>& directories) { @@ -70,6 +75,14 @@ namespace WebCore { m_pluginDirectories = directories; } + void setClient(PluginDatabaseClient* client) + { + m_client = client; + } + + static Vector<String> defaultPluginDirectories(); + Vector<String> pluginDirectories() const { return m_pluginDirectories; } + private: void getPluginPathsInDirectories(HashSet<String>&) const; void getDeletedPlugins(PluginSet&) const; @@ -78,16 +91,15 @@ namespace WebCore { bool add(PassRefPtr<PluginPackage>); void remove(PluginPackage*); - PluginPackage* pluginForMIMEType(const String& mimeType); String MIMETypeForExtension(const String& extension) const; - static Vector<String> defaultPluginDirectories(); - Vector<String> m_pluginDirectories; HashSet<String> m_registeredMIMETypes; PluginSet m_plugins; HashMap<String, RefPtr<PluginPackage> > m_pluginsByPath; HashMap<String, time_t> m_pluginPathsWithTimes; + HashMap<String, RefPtr<PluginPackage> > m_preferredPlugins; + PluginDatabaseClient* m_client; }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/plugins/PluginDatabaseClient.h b/src/3rdparty/webkit/WebCore/plugins/PluginDatabaseClient.h new file mode 100644 index 000000000..b19ab831f --- /dev/null +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/plugins/PluginPackage.cpp b/src/3rdparty/webkit/WebCore/plugins/PluginPackage.cpp index 8adba9836..8f2dfa990 100644 --- a/src/3rdparty/webkit/WebCore/plugins/PluginPackage.cpp +++ b/src/3rdparty/webkit/WebCore/plugins/PluginPackage.cpp @@ -22,7 +22,7 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" @@ -47,7 +47,7 @@ PluginPackage::~PluginPackage() // course would cause a crash, so we check to call unload before we // ASSERT. // FIXME: There is probably a better way to fix this. - if (m_loadCount == 0) + if (!m_loadCount) unloadWithoutShutdown(); else unload(); @@ -59,7 +59,7 @@ void PluginPackage::freeLibrarySoon() { ASSERT(!m_freeLibraryTimer.isActive()); ASSERT(m_module); - ASSERT(m_loadCount == 0); + ASSERT(!m_loadCount); m_freeLibraryTimer.startOneShot(0); } @@ -67,7 +67,7 @@ void PluginPackage::freeLibrarySoon() void PluginPackage::freeLibraryTimerFired(Timer<PluginPackage>*) { ASSERT(m_module); - ASSERT(m_loadCount == 0); + ASSERT(!m_loadCount); unloadModule(m_module); m_module = 0; @@ -100,7 +100,8 @@ int PluginPackage::compare(const PluginPackage& compareTo) const } PluginPackage::PluginPackage(const String& path, const time_t& lastModified) - : m_isLoaded(false) + : m_isEnabled(true) + , m_isLoaded(false) , m_loadCount(0) , m_path(path) , m_moduleVersion(0) @@ -112,6 +113,7 @@ PluginPackage::PluginPackage(const String& path, const time_t& lastModified) m_parentDirectory = m_path.left(m_path.length() - m_fileName.length() - 1); } +#if !PLATFORM(SYMBIAN) void PluginPackage::unload() { if (!m_isLoaded) @@ -124,13 +126,14 @@ void PluginPackage::unload() unloadWithoutShutdown(); } +#endif //!PLATFORM(SYMBIAN) void PluginPackage::unloadWithoutShutdown() { if (!m_isLoaded) return; - ASSERT(m_loadCount == 0); + ASSERT(!m_loadCount); ASSERT(m_module); // <rdar://5530519>: Crash when closing tab with pdf file (Reader 7 only) @@ -144,6 +147,11 @@ void PluginPackage::unloadWithoutShutdown() m_isLoaded = false; } +void PluginPackage::setEnabled(bool enabled) +{ + m_isEnabled = enabled; +} + PassRefPtr<PluginPackage> PluginPackage::createPackage(const String& path, const time_t& lastModified) { RefPtr<PluginPackage> package = adoptRef(new PluginPackage(path, lastModified)); @@ -177,6 +185,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); @@ -243,7 +252,7 @@ void PluginPackage::determineModuleVersionFromDescription() void PluginPackage::initializeBrowserFuncs() { memset(&m_browserFuncs, 0, sizeof(m_browserFuncs)); - m_browserFuncs.size = sizeof (m_browserFuncs); + m_browserFuncs.size = sizeof(m_browserFuncs); m_browserFuncs.version = NP_VERSION_MINOR; m_browserFuncs.geturl = NPN_GetURL; @@ -310,15 +319,24 @@ bool PluginPackage::equal(const PluginPackage& a, const PluginPackage& b) { return a.m_description == b.m_description; } +#endif int PluginPackage::compareFileVersion(const PlatformModuleVersion& compareVersion) const { // return -1, 0, or 1 if plug-in version is less than, equal to, or greater than // the passed version + +#if PLATFORM(WIN_OS) + if (m_moduleVersion.mostSig != compareVersion.mostSig) + return m_moduleVersion.mostSig > compareVersion.mostSig ? 1 : -1; + if (m_moduleVersion.leastSig != compareVersion.leastSig) + return m_moduleVersion.leastSig > compareVersion.leastSig ? 1 : -1; +#else if (m_moduleVersion != compareVersion) return m_moduleVersion > compareVersion ? 1 : -1; +#endif + return 0; } -#endif } diff --git a/src/3rdparty/webkit/WebCore/plugins/PluginPackage.h b/src/3rdparty/webkit/WebCore/plugins/PluginPackage.h index 02d0dfce5..d409ab60b 100644 --- a/src/3rdparty/webkit/WebCore/plugins/PluginPackage.h +++ b/src/3rdparty/webkit/WebCore/plugins/PluginPackage.h @@ -21,7 +21,7 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef PluginPackage_H @@ -36,6 +36,11 @@ #include <wtf/HashMap.h> #include <wtf/RefCounted.h> +#if PLATFORM(SYMBIAN) +class QPluginLoader; +class NPInterface; +#endif + namespace WebCore { typedef HashMap<String, String> MIMEToDescriptionsMap; typedef HashMap<String, Vector<String> > MIMEToExtensionsMap; @@ -44,7 +49,7 @@ namespace WebCore { public: ~PluginPackage(); static PassRefPtr<PluginPackage> createPackage(const String& path, const time_t& lastModified); - + const String& name() const { return m_name; } const String& description() const { return m_description; } const String& path() const { return m_path; } @@ -62,14 +67,25 @@ namespace WebCore { void unload(); void unloadWithoutShutdown(); + bool isEnabled() const { return m_isEnabled; } + void setEnabled(bool); + const NPPluginFuncs* pluginFuncs() const { return &m_pluginFuncs; } int compareFileVersion(const PlatformModuleVersion&) const; int compare(const PluginPackage&) const; PluginQuirkSet quirks() const { return m_quirks; } const PlatformModuleVersion& version() const { return m_moduleVersion; } +#if PLATFORM(SYMBIAN) + NPInterface* npInterface() const { return m_npInterface; } +#endif // PLATFORM(SYMBIAN) private: PluginPackage(const String& path, const time_t& lastModified); + +#if PLATFORM(SYMBIAN) + NPInterface* m_npInterface; + QPluginLoader* m_pluginLoader; +#endif // PLATFORM(SYMBIAN) bool fetchInfo(); bool isPluginBlacklisted(); void determineQuirks(const String& mimeType); @@ -77,6 +93,7 @@ namespace WebCore { void determineModuleVersionFromDescription(); void initializeBrowserFuncs(); + bool m_isEnabled; bool m_isLoaded; int m_loadCount; diff --git a/src/3rdparty/webkit/WebCore/plugins/PluginPackageNone.cpp b/src/3rdparty/webkit/WebCore/plugins/PluginPackageNone.cpp index 487450a35..b943d88af 100644 --- a/src/3rdparty/webkit/WebCore/plugins/PluginPackageNone.cpp +++ b/src/3rdparty/webkit/WebCore/plugins/PluginPackageNone.cpp @@ -26,52 +26,20 @@ #include "config.h" #include "PluginPackage.h" -#include "CString.h" -#include "MIMETypeRegistry.h" -#include "NotImplemented.h" -#include "npruntime_impl.h" -#include "PluginDatabase.h" -#include "PluginDebug.h" - namespace WebCore { void PluginPackage::determineQuirks(const String&) { - notImplemented(); } bool PluginPackage::fetchInfo() { - notImplemented(); return false; } bool PluginPackage::load() { - notImplemented(); - return false; -} - -#if !ENABLE(PLUGIN_PACKAGE_SIMPLE_HASH) -unsigned PluginPackage::hash() const -{ - notImplemented(); - - return 0; -} - -bool PluginPackage::equal(const PluginPackage&, const PluginPackage&) -{ - notImplemented(); return false; } -int PluginPackage::compareFileVersion(const PlatformModuleVersion&) const -{ - notImplemented(); - return 0; -} - -#endif - } diff --git a/src/3rdparty/webkit/WebCore/plugins/PluginQuirkSet.h b/src/3rdparty/webkit/WebCore/plugins/PluginQuirkSet.h index b652c6e32..de29baf8a 100644 --- a/src/3rdparty/webkit/WebCore/plugins/PluginQuirkSet.h +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/plugins/PluginStream.cpp b/src/3rdparty/webkit/WebCore/plugins/PluginStream.cpp index d2d5d3c0a..cd9f83dbd 100644 --- a/src/3rdparty/webkit/WebCore/plugins/PluginStream.cpp +++ b/src/3rdparty/webkit/WebCore/plugins/PluginStream.cpp @@ -248,6 +248,11 @@ void PluginStream::destroyStream() bool newStreamCalled = m_stream.ndata; + // Protect from destruction if: + // NPN_DestroyStream is called from NPP_NewStream or + // PluginStreamClient::streamDidFinishLoading() removes the last reference + RefPtr<PluginStream> protect(this); + if (newStreamCalled) { if (m_reason == NPRES_DONE && (m_transferMode == NP_ASFILE || m_transferMode == NP_ASFILEONLY)) { ASSERT(!m_path.isNull()); @@ -281,9 +286,6 @@ void PluginStream::destroyStream() m_loader->setDefersLoading(true); if (!newStreamCalled && m_quirks.contains(PluginQuirkFlashURLNotifyBug) && equalIgnoringCase(m_resourceRequest.httpMethod(), "POST")) { - // Protect the stream if NPN_DestroyStream is called from NPP_NewStream - RefPtr<PluginStream> protect(this); - m_transferMode = NP_NORMAL; m_stream.url = ""; m_stream.notifyData = m_notifyData; @@ -303,8 +305,6 @@ void PluginStream::destroyStream() m_streamState = StreamStopped; - // streamDidFinishLoading can cause us to be deleted. - RefPtr<PluginStream> protect(this); if (!m_loadManually) m_client->streamDidFinishLoading(this); diff --git a/src/3rdparty/webkit/WebCore/plugins/PluginView.cpp b/src/3rdparty/webkit/WebCore/plugins/PluginView.cpp index 2cecdc4e7..d69f8a731 100644 --- a/src/3rdparty/webkit/WebCore/plugins/PluginView.cpp +++ b/src/3rdparty/webkit/WebCore/plugins/PluginView.cpp @@ -53,6 +53,7 @@ #include "JSDOMBinding.h" #include "ScriptController.h" #include "ScriptValue.h" +#include "SecurityOrigin.h" #include "PluginDatabase.h" #include "PluginDebug.h" #include "PluginMainThreadScheduler.h" @@ -123,12 +124,12 @@ void PluginView::setFrameRect(const IntRect& rect) updatePluginWidget(); -#if PLATFORM(WIN_OS) - // On Windows, always call plugin to change geometry. +#if PLATFORM(WIN_OS) || PLATFORM(SYMBIAN) + // On Windows and Symbian, 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 } @@ -147,6 +148,54 @@ void PluginView::handleEvent(Event* event) handleMouseEvent(static_cast<MouseEvent*>(event)); else if (event->isKeyboardEvent()) handleKeyboardEvent(static_cast<KeyboardEvent*>(event)); +#if defined(Q_WS_X11) && ENABLE(NETSCAPE_PLUGIN_API) + 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(); } bool PluginView::start() @@ -154,6 +203,8 @@ bool PluginView::start() if (m_isStarted) return false; + m_isWaitingToStart = false; + PluginMainThreadScheduler::scheduler().registerPlugin(m_instance); ASSERT(m_plugin); @@ -164,14 +215,17 @@ bool PluginView::start() PluginView::setCurrentPluginView(this); JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); setCallingPlugin(true); - npErr = m_plugin->pluginFuncs()->newp((NPMIMEType)m_mimeType.data(), m_instance, m_mode, m_paramCount, m_paramNames, m_paramValues, NULL); + npErr = m_plugin->pluginFuncs()->newp((NPMIMEType)m_mimeType.utf8().data(), m_instance, m_mode, m_paramCount, m_paramNames, m_paramValues, NULL); setCallingPlugin(false); LOG_NPERROR(npErr); PluginView::setCurrentPluginView(0); } - if (npErr != NPERR_NO_ERROR) + if (npErr != NPERR_NO_ERROR) { + m_status = PluginStatusCanNotLoadPlugin; + PluginMainThreadScheduler::scheduler().unregisterPlugin(m_instance); return false; + } m_isStarted = true; @@ -182,9 +236,138 @@ bool PluginView::start() load(frameLoadRequest, false, 0); } + m_status = PluginStatusLoadedSuccessfully; + + 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 (m_plugin && !(m_plugin->quirks().contains(PluginQuirkDontUnloadPlugin))) + 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; + HashSet<RefPtr<PluginStream> >::iterator end = streams.end(); + for (HashSet<RefPtr<PluginStream> >::iterator it = streams.begin(); it != end; ++it) { + (*it)->stop(); + disconnectStream((*it).get()); + } + + ASSERT(m_streams.isEmpty()); + + m_isStarted = false; + + JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); + +#if ENABLE(NETSCAPE_PLUGIN_API) +#if !PLATFORM(WX) // FIXME: Revisit this when implementing plugins for wx +#ifdef XP_WIN + // Unsubclass the window + if (m_isWindowed) { +#if PLATFORM(WINCE) + WNDPROC currentWndProc = (WNDPROC)GetWindowLong(platformPluginWidget(), GWL_WNDPROC); + + if (currentWndProc == PluginViewWndProc) + SetWindowLong(platformPluginWidget(), GWL_WNDPROC, (LONG)m_pluginWndProc); +#else + WNDPROC currentWndProc = (WNDPROC)GetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC); + + if (currentWndProc == PluginViewWndProc) + SetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC, (LONG)m_pluginWndProc); +#endif + } +#endif // XP_WIN +#endif // !PLATFORM(WX) +#endif // ENABLE(NETSCAPE_PLUGIN_API) + +#if !defined(XP_MACOSX) + // Clear the window + m_npWindow.window = 0; + + if (m_plugin->pluginFuncs()->setwindow && !m_plugin->quirks().contains(PluginQuirkDontSetNullWindowHandleOnDestroy)) { + PluginView::setCurrentPluginView(this); + setCallingPlugin(true); + m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow); + setCallingPlugin(false); + PluginView::setCurrentPluginView(0); + } + +#ifdef XP_UNIX + if (m_isWindowed && m_npWindow.ws_info) + delete (NPSetWindowCallbackStruct *)m_npWindow.ws_info; + m_npWindow.ws_info = 0; +#endif + +#endif // !defined(XP_MACOSX) + + PluginMainThreadScheduler::scheduler().unregisterPlugin(m_instance); + + NPSavedData* savedData = 0; + PluginView::setCurrentPluginView(this); + setCallingPlugin(true); + NPError npErr = m_plugin->pluginFuncs()->destroy(m_instance, &savedData); + setCallingPlugin(false); + LOG_NPERROR(npErr); + PluginView::setCurrentPluginView(0); + +#if ENABLE(NETSCAPE_PLUGIN_API) + if (savedData) { + // TODO: Actually save this data instead of just discarding it + if (savedData->buf) + NPN_MemFree(savedData->buf); + NPN_MemFree(savedData); + } +#endif + + m_instance->pdata = 0; +} + void PluginView::setCurrentPluginView(PluginView* pluginView) { s_currentPluginView = pluginView; @@ -211,7 +394,7 @@ static bool getString(ScriptController* proxy, JSValue result, String& string) return false; JSLock lock(JSC::SilenceAssertionsOnly); - ExecState* exec = proxy->globalObject()->globalExec(); + ExecState* exec = proxy->globalObject(pluginWorld())->globalExec(); UString ustring = result.toString(exec); exec->clearException(); @@ -221,6 +404,9 @@ static bool getString(ScriptController* proxy, JSValue result, String& string) void PluginView::performRequest(PluginRequest* request) { + if (!m_isStarted) + return; + // 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(); @@ -264,7 +450,7 @@ void PluginView::performRequest(PluginRequest* request) // 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; - JSValue result = m_parentFrame->loader()->executeScript(jsString, request->shouldAllowPopups()).jsValue(); + JSValue result = m_parentFrame->script()->executeScript(jsString, request->shouldAllowPopups()).jsValue(); if (targetFrameName.isNull()) { String resultString; @@ -331,9 +517,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); @@ -522,7 +707,7 @@ PassRefPtr<JSC::Bindings::Instance> PluginView::bindingInstance() #if ENABLE(NETSCAPE_PLUGIN_API) NPObject* object = 0; - if (!m_plugin || !m_plugin->pluginFuncs()->getvalue) + if (!m_isStarted || !m_plugin || !m_plugin->pluginFuncs()->getvalue) return 0; // On Windows, calling Java's NPN_GetValue can allow the message loop to @@ -582,6 +767,9 @@ void PluginView::setParameters(const Vector<String>& paramNames, const Vector<St if (m_plugin->quirks().contains(PluginQuirkRemoveWindowlessVideoParam) && equalIgnoringCase(paramNames[i], "windowlessvideo")) continue; + if (paramNames[i] == "pluginspage") + m_pluginsPage = paramValues[i]; + m_paramNames[paramCount] = createUTF8String(paramNames[i]); m_paramValues[paramCount] = createUTF8String(paramValues[i]); @@ -604,7 +792,7 @@ PluginView::PluginView(Frame* parentFrame, const IntSize& size, PluginPackage* p , m_popPopupsStateTimer(this, &PluginView::popPopupsStateTimerFired) , m_paramNames(0) , m_paramValues(0) - , m_instance(0) + , m_mimeType(mimeType) #if defined(XP_MACOSX) , m_isWindowed(false) #else @@ -612,7 +800,8 @@ PluginView::PluginView(Frame* parentFrame, const IntSize& size, PluginPackage* p #endif , m_isTransparent(false) , m_haveInitialized(false) -#if PLATFORM(GTK) || defined(Q_WS_X11) + , m_isWaitingToStart(false) +#if defined(XP_UNIX) || defined(Q_WS_X11) , m_needsXEmbed(false) #endif #if PLATFORM(WIN_OS) && !PLATFORM(WX) && ENABLE(NETSCAPE_PLUGIN_API) @@ -620,6 +809,7 @@ PluginView::PluginView(Frame* parentFrame, const IntSize& size, PluginPackage* p , m_lastMessage(0) , m_isCallingPluginWndProc(false) , m_wmPrintHDC(0) + , m_haveUpdatedPluginWidget(false) #endif #if (PLATFORM(QT) && PLATFORM(WIN_OS)) || defined(XP_MACOSX) , m_window(0) @@ -628,9 +818,18 @@ PluginView::PluginView(Frame* parentFrame, const IntSize& size, PluginPackage* p , m_drawingModel(NPDrawingModel(-1)) , m_eventModel(NPEventModel(-1)) #endif +#if defined(Q_WS_X11) && ENABLE(NETSCAPE_PLUGIN_API) + , 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) + , m_isHalted(false) + , m_hasBeenHalted(false) { if (!m_plugin) { m_status = PluginStatusCanNotFindPlugin; @@ -641,8 +840,6 @@ PluginView::PluginView(Frame* parentFrame, const IntSize& size, PluginPackage* p m_instance->ndata = this; m_instance->pdata = 0; - m_mimeType = mimeType.utf8(); - setParameters(paramNames, paramValues); memset(&m_npWindow, 0, sizeof(m_npWindow)); @@ -1005,4 +1202,43 @@ void PluginView::paintMissingPluginIcon(GraphicsContext* context, const IntRect& context->restore(); } +static const char* MozillaUserAgent = "Mozilla/5.0 (" +#if defined(XP_MACOSX) + "Macintosh; U; Intel Mac OS X;" +#elif defined(XP_WIN) + "Windows; U; Windows NT 5.1;" +#elif defined(XP_UNIX) +// 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"; + +const char* PluginView::userAgent() +{ + if (m_plugin->quirks().contains(PluginQuirkWantsMozillaUserAgent)) + return MozillaUserAgent; + + if (m_userAgent.isNull()) + m_userAgent = m_parentFrame->loader()->userAgent(m_url).utf8(); + + return m_userAgent.data(); +} + +#if ENABLE(NETSCAPE_PLUGIN_API) +const char* PluginView::userAgentStatic() +{ + return MozillaUserAgent; +} +#endif + + +Node* PluginView::node() const +{ + return m_element; +} + } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/plugins/PluginView.h b/src/3rdparty/webkit/WebCore/plugins/PluginView.h index 95d73db5e..0a57fa62e 100644 --- a/src/3rdparty/webkit/WebCore/plugins/PluginView.h +++ b/src/3rdparty/webkit/WebCore/plugins/PluginView.h @@ -29,6 +29,7 @@ #include "CString.h" #include "FrameLoadRequest.h" +#include "HaltablePlugin.h" #include "IntRect.h" #include "KURL.h" #include "PlatformString.h" @@ -60,6 +61,7 @@ namespace JSC { namespace WebCore { class Element; class Frame; + class Image; class KeyboardEvent; class MouseEvent; class KURL; @@ -106,7 +108,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(); @@ -177,6 +179,10 @@ namespace WebCore { void focusPluginElement(); + const String& pluginsPage() const { return m_pluginsPage; } + const String& mimeType() const { return m_mimeType; } + const KURL& url() const { return m_url; } + #if PLATFORM(WIN_OS) && !PLATFORM(WX) && ENABLE(NETSCAPE_PLUGIN_API) static LRESULT CALLBACK PluginViewWndProc(HWND, UINT, WPARAM, LPARAM); LRESULT wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); @@ -189,15 +195,28 @@ namespace WebCore { void didFinishLoading(); void didFail(const ResourceError&); + // HaltablePlugin + virtual void halt(); + virtual void restart(); + virtual Node* node() const; + + bool isHalted() const { return m_isHalted; } + bool hasBeenHalted() const { return m_hasBeenHalted; } + static bool isCallingPlugin(); + bool start(); + private: PluginView(Frame* parentFrame, const IntSize&, PluginPackage*, Element*, const KURL&, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually); void setParameters(const Vector<String>& paramNames, const Vector<String>& paramValues); + bool startOrAddToUnstartedList(); + void removeFromUnstartedListIfNecessary(); void init(); - bool start(); + 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); @@ -208,7 +227,7 @@ namespace WebCore { void invalidateWindowlessPluginRect(const IntRect&); #if PLATFORM(WIN_OS) && !PLATFORM(WX) && ENABLE(NETSCAPE_PLUGIN_API) - void paintWindowedPluginIntoContext(GraphicsContext*, const IntRect&) const; + void paintWindowedPluginIntoContext(GraphicsContext*, const IntRect&); static HDC WINAPI hookedBeginPaint(HWND, PAINTSTRUCT*); static BOOL WINAPI hookedEndPaint(HWND, const PAINTSTRUCT*); #endif @@ -240,13 +259,23 @@ namespace WebCore { void handleKeyboardEvent(KeyboardEvent*); void handleMouseEvent(MouseEvent*); +#if defined(Q_WS_X11) && ENABLE(NETSCAPE_PLUGIN_API) + void handleFocusInEvent(); + void handleFocusOutEvent(); +#endif + +#if PLATFORM(WIN_OS) + void paintIntoTransformedContext(HDC); + PassRefPtr<Image> snapshot(); +#endif int m_mode; int m_paramCount; char** m_paramNames; char** m_paramValues; + String m_pluginsPage; - CString m_mimeType; + String m_mimeType; CString m_userAgent; NPP m_instance; @@ -261,8 +290,9 @@ namespace WebCore { bool m_isWindowed; bool m_isTransparent; 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 @@ -272,6 +302,7 @@ namespace WebCore { unsigned m_lastMessage; bool m_isCallingPluginWndProc; HDC m_wmPrintHDC; + bool m_haveUpdatedPluginWidget; #endif #if (PLATFORM(QT) && PLATFORM(WIN_OS)) || defined(XP_MACOSX) @@ -283,12 +314,13 @@ public: void setPlatformPluginWidget(PlatformPluginWidget widget) { m_window = widget; } #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) || PLATFORM(SYMBIAN) void setNPWindowIfNeeded(); #elif defined(XP_MACOSX) NP_CGContext m_npCgContext; @@ -301,8 +333,14 @@ private: Point globalMousePosForPlugin() const; #endif -#if defined(Q_WS_X11) +#if defined(Q_WS_X11) && ENABLE(NETSCAPE_PLUGIN_API) 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 @@ -313,6 +351,9 @@ private: bool m_isJavaScriptPaused; + bool m_isHalted; + bool m_hasBeenHalted; + static PluginView* s_currentPluginView; }; diff --git a/src/3rdparty/webkit/WebCore/plugins/PluginViewNone.cpp b/src/3rdparty/webkit/WebCore/plugins/PluginViewNone.cpp index a3b6a178b..725af82e5 100644 --- a/src/3rdparty/webkit/WebCore/plugins/PluginViewNone.cpp +++ b/src/3rdparty/webkit/WebCore/plugins/PluginViewNone.cpp @@ -26,131 +26,98 @@ #include "config.h" #include "PluginView.h" -#include "NotImplemented.h" -#include "PluginPackage.h" - using namespace WTF; namespace WebCore { void PluginView::setFocus() { - notImplemented(); } void PluginView::show() { - notImplemented(); } void PluginView::hide() { - notImplemented(); } void PluginView::paint(GraphicsContext*, const IntRect&) { - notImplemented(); } void PluginView::handleKeyboardEvent(KeyboardEvent*) { - notImplemented(); } void PluginView::handleMouseEvent(MouseEvent*) { - notImplemented(); } void PluginView::setParent(ScrollView*) { - notImplemented(); } void PluginView::setNPWindowRect(const IntRect&) { - notImplemented(); -} - -void PluginView::stop() -{ - notImplemented(); } -const char* PluginView::userAgent() -{ - notImplemented(); - return 0; -} - -#if ENABLE(NETSCAPE_PLUGIN_API) -const char* PluginView::userAgentStatic() -{ - notImplemented(); - return 0; -} -#endif - NPError PluginView::handlePostReadFile(Vector<char>&, uint32, const char*) { - notImplemented(); - return 0; } NPError PluginView::getValue(NPNVariable, void*) { - notImplemented(); return 0; } #if ENABLE(NETSCAPE_PLUGIN_API) NPError PluginView::getValueStatic(NPNVariable variable, void* value) { - notImplemented(); return 0; } #endif void PluginView::invalidateRect(NPRect*) { - notImplemented(); } void PluginView::invalidateRect(const IntRect&) { - notImplemented(); } void PluginView::invalidateRegion(NPRegion) { - notImplemented(); } void PluginView::forceRedraw() { - notImplemented(); } -PluginView::~PluginView() +bool PluginView::platformStart() { - notImplemented(); + return true; } -void PluginView::init() +void PluginView::platformDestroy() { - notImplemented(); } void PluginView::setParentVisible(bool) { - notImplemented(); } void PluginView::updatePluginWidget() { - notImplemented(); +} + +void PluginView::halt() +{ +} + +void PluginView::restart() +{ } } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/plugins/mac/PluginPackageMac.cpp b/src/3rdparty/webkit/WebCore/plugins/mac/PluginPackageMac.cpp index bf6a81bf0..325bc4d6c 100644 --- a/src/3rdparty/webkit/WebCore/plugins/mac/PluginPackageMac.cpp +++ b/src/3rdparty/webkit/WebCore/plugins/mac/PluginPackageMac.cpp @@ -159,7 +159,8 @@ bool PluginPackage::fetchInfo() plist = readPListFile(path.get(), /*createFile*/ true, m_module); } - mimeDict = (CFDictionaryRef)CFDictionaryGetValue(plist.get(), CFSTR("WebPluginMIMETypes")); + if (plist) + mimeDict = (CFDictionaryRef)CFDictionaryGetValue(plist.get(), CFSTR("WebPluginMIMETypes")); } if (!mimeDict) @@ -246,9 +247,6 @@ bool PluginPackage::fetchInfo() bool PluginPackage::isPluginBlacklisted() { - if (name() == "Silverlight Plug-In" || name().startsWith("QuickTime Plug-in")) - return true; - return false; } diff --git a/src/3rdparty/webkit/WebCore/plugins/mac/PluginViewMac.cpp b/src/3rdparty/webkit/WebCore/plugins/mac/PluginViewMac.cpp index 721ec2909..6521c84ef 100644 --- a/src/3rdparty/webkit/WebCore/plugins/mac/PluginViewMac.cpp +++ b/src/3rdparty/webkit/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,70 +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* widget = client->ownerWidget()) { + setPlatformPluginWidget(widget); + } + } +#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); -} - -PluginView::~PluginView() -{ - 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; + return true; } -void PluginView::stop() +void PluginView::platformDestroy() { - if (!m_isStarted) - return; - - LOG(Plugins, "PluginView::stop(): Stopping plug-in '%s'", m_plugin->name().utf8().data()); - - HashSet<RefPtr<PluginStream> > streams = m_streams; - HashSet<RefPtr<PluginStream> >::iterator end = streams.end(); - for (HashSet<RefPtr<PluginStream> >::iterator it = streams.begin(); it != end; ++it) { - (*it)->stop(); - disconnectStream((*it).get()); - } - - ASSERT(m_streams.isEmpty()); - - m_isStarted = false; - - JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); - - PluginMainThreadScheduler::scheduler().unregisterPlugin(m_instance); - - // Destroy the plugin - PluginView::setCurrentPluginView(this); - setCallingPlugin(true); - m_plugin->pluginFuncs()->destroy(m_instance, 0); - setCallingPlugin(false); - PluginView::setCurrentPluginView(0); - - m_instance->pdata = 0; + if (platformPluginWidget()) + setPlatformPluginWidget(0); } // Used before the plugin view has been initialized properly, and as a @@ -488,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; @@ -496,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) @@ -724,24 +667,6 @@ bool PluginView::dispatchNPEvent(NPEvent& event) // ------------------- Miscellaneous ------------------ -static const char* MozillaUserAgent = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0"; - -const char* PluginView::userAgent() -{ - if (m_plugin->quirks().contains(PluginQuirkWantsMozillaUserAgent)) - return MozillaUserAgent; - - if (m_userAgent.isNull()) - m_userAgent = m_parentFrame->loader()->userAgent(m_url).utf8(); - - return m_userAgent.data(); -} - -const char* PluginView::userAgentStatic() -{ - return MozillaUserAgent; -} - NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf) { String filename(buf, len); @@ -767,6 +692,14 @@ NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const c return NPERR_NO_ERROR; } +void PluginView::halt() +{ +} + +void PluginView::restart() +{ +} + } // namespace WebCore #else diff --git a/src/3rdparty/webkit/WebCore/plugins/qt/PluginContainerQt.cpp b/src/3rdparty/webkit/WebCore/plugins/qt/PluginContainerQt.cpp index 59ab5bc06..cb894a7bf 100644 --- a/src/3rdparty/webkit/WebCore/plugins/qt/PluginContainerQt.cpp +++ b/src/3rdparty/webkit/WebCore/plugins/qt/PluginContainerQt.cpp @@ -73,6 +73,7 @@ PluginContainerQt::PluginContainerQt(PluginView* view, QWidget* parent) PluginContainerQt::~PluginContainerQt() { delete m_clientWrapper; + m_pluginView->setPlatformPluginWidget(0); } void PluginContainerQt::on_clientClosed() diff --git a/src/3rdparty/webkit/WebCore/plugins/qt/PluginPackageQt.cpp b/src/3rdparty/webkit/WebCore/plugins/qt/PluginPackageQt.cpp index b9c1656b9..811992444 100644 --- a/src/3rdparty/webkit/WebCore/plugins/qt/PluginPackageQt.cpp +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/plugins/qt/PluginViewQt.cpp b/src/3rdparty/webkit/WebCore/plugins/qt/PluginViewQt.cpp index 883c9aa97..e61736b65 100644 --- a/src/3rdparty/webkit/WebCore/plugins/qt/PluginViewQt.cpp +++ b/src/3rdparty/webkit/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" @@ -45,6 +48,7 @@ #include "NotImplemented.h" #include "Page.h" #include "PlatformMouseEvent.h" +#include "PlatformKeyboardEvent.h" #include "PluginContainerQt.h" #include "PluginDebug.h" #include "PluginPackage.h" @@ -55,10 +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; @@ -76,7 +91,7 @@ using namespace HTMLNames; void PluginView::updatePluginWidget() { - if (!parent() || !m_isWindowed || !platformPluginWidget()) + if (!parent()) return; ASSERT(parent()->isFrameView()); @@ -92,6 +107,15 @@ void PluginView::updatePluginWidget() if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect) return; + if (!m_isWindowed && m_windowRect.size() != oldWindowRect.size()) { + if (m_drawable) + XFreePixmap(QX11Info::display(), m_drawable); + + 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; @@ -146,18 +170,282 @@ 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(); + IntRect exposedRect(rect); + exposedRect.intersect(frameRect()); + exposedRect.move(-frameRect().x(), -frameRect().y()); + + QPixmap qtDrawable = QPixmap::fromX11Pixmap(m_drawable, QPixmap::ExplicitlyShared); + const int drawableDepth = ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth; + ASSERT(drawableDepth == qtDrawable.depth()); + + // When printing, Qt uses a QPicture to capture the output in preview mode. The + // QPicture holds a reference to the X Pixmap. As a result, the print preview would + // update itself when the X Pixmap changes. To prevent this, we create a copy. + if (m_element->document()->printing()) + qtDrawable = qtDrawable.copy(); + + 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 = client && 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() + exposedRect.x(), offset.y() + m_windowRect.y() + exposedRect.y(), + exposedRect.width(), exposedRect.height(), exposedRect.x(), exposedRect.y()); + } else { // no backing store, clean the pixmap because the plugin thinks its transparent + QPainter painter(&qtDrawable); + painter.fillRect(exposedRect, 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 = qtDrawable.handle(); + exposeEvent.x = exposedRect.x(); + exposeEvent.y = exposedRect.y(); + exposeEvent.width = exposedRect.x() + exposedRect.width(); // flash bug? it thinks width is the right in transparent mode + exposeEvent.height = exposedRect.y() + exposedRect.height(); // flash bug? it thinks height is the bottom in transparent mode + + dispatchNPEvent(xevent); + + if (syncX) + XSync(m_pluginDisplay, False); // sync changes by plugin + + painter->drawPixmap(QPoint(frameRect().x() + exposedRect.x(), frameRect().y() + exposedRect.y()), qtDrawable, + exposedRect); +} + +// TODO: Unify across ports. +bool PluginView::dispatchNPEvent(NPEvent& event) +{ + if (!m_plugin->pluginFuncs()->event) + return false; + + PluginView::setCurrentPluginView(this); + JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); + setCallingPlugin(true); + bool accepted = m_plugin->pluginFuncs()->event(m_instance, &event); + setCallingPlugin(false); + PluginView::setCurrentPluginView(0); + + return accepted; +} + +void setSharedXEventFields(XEvent* xEvent, QWidget* ownerWidget) +{ + xEvent->xany.serial = 0; // we are unaware of the last request processed by X Server + xEvent->xany.send_event = false; + xEvent->xany.display = QX11Info::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 = ownerWidget ? ownerWidget->window()->handle() : 0; +} + +void PluginView::initXEvent(XEvent* xEvent) +{ + memset(xEvent, 0, sizeof(XEvent)); + + QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient(); + QWidget* ownerWidget = client ? client->ownerWidget() : 0; + setSharedXEventFields(xEvent, ownerWidget); +} + +void setXKeyEventSpecificFields(XEvent* xEvent, KeyboardEvent* event) +{ + QKeyEvent* qKeyEvent = event->keyEvent()->qtEvent(); + + 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; } void PluginView::handleKeyboardEvent(KeyboardEvent* event) { - notImplemented(); + if (m_isWindowed) + return; + + if (event->type() != eventNames().keydownEvent && event->type() != eventNames().keyupEvent) + return; + + 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) { - notImplemented(); + 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) @@ -170,7 +458,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() @@ -178,36 +467,53 @@ void PluginView::setNPWindowIfNeeded() if (!m_isStarted || !parent() || !m_plugin->pluginFuncs()->setwindow) return; + // If the plugin didn't load sucessfully, no point in calling setwindow + if (m_status != PluginStatusLoadedSuccessfully) + return; + // On Unix, only call plugin if it's full-page or windowed if (m_mode != NP_FULL && m_mode != NP_EMBED) return; + // Check if the platformPluginWidget still exists + if (m_isWindowed && !platformPluginWidget()) + return; + if (!m_hasPendingGeometryChange) 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) { + 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); @@ -227,70 +533,6 @@ void PluginView::setParentVisible(bool visible) platformPluginWidget()->setVisible(visible); } -void PluginView::stop() -{ - if (!m_isStarted) - return; - - HashSet<RefPtr<PluginStream> > streams = m_streams; - HashSet<RefPtr<PluginStream> >::iterator end = streams.end(); - for (HashSet<RefPtr<PluginStream> >::iterator it = streams.begin(); it != end; ++it) { - (*it)->stop(); - disconnectStream((*it).get()); - } - - ASSERT(m_streams.isEmpty()); - - m_isStarted = false; - - JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); - - PluginMainThreadScheduler::scheduler().unregisterPlugin(m_instance); - - // Clear the window - m_npWindow.window = 0; - if (m_plugin->pluginFuncs()->setwindow && !m_plugin->quirks().contains(PluginQuirkDontSetNullWindowHandleOnDestroy)) { - PluginView::setCurrentPluginView(this); - setCallingPlugin(true); - m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow); - setCallingPlugin(false); - PluginView::setCurrentPluginView(0); - } - - delete (NPSetWindowCallbackStruct *)m_npWindow.ws_info; - m_npWindow.ws_info = 0; - - // Destroy the plugin - { - PluginView::setCurrentPluginView(this); - setCallingPlugin(true); - m_plugin->pluginFuncs()->destroy(m_instance, 0); - setCallingPlugin(false); - PluginView::setCurrentPluginView(0); - } - - m_instance->pdata = 0; -} - -static const char* MozillaUserAgent = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0"; - -const char* PluginView::userAgent() -{ - if (m_plugin->quirks().contains(PluginQuirkWantsMozillaUserAgent)) - return MozillaUserAgent; - - if (m_userAgent.isNull()) - m_userAgent = m_parentFrame->loader()->userAgent(m_url).utf8(); - - return m_userAgent.data(); -} - -const char* PluginView::userAgentStatic() -{ - // FIXME - Just say we are Mozilla - return MozillaUserAgent; -} - NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf) { String filename(buf, len); @@ -336,6 +578,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; } @@ -347,10 +593,7 @@ NPError PluginView::getValue(NPNVariable variable, void* value) switch (variable) { case NPNVxDisplay: - if (platformPluginWidget()) - *(void **)value = platformPluginWidget()->x11Info().display(); - else - *(void **)value = m_parentFrame->view()->hostWindow()->platformWindow()->x11Info().display(); + *(void **)value = QX11Info::display(); return NPERR_NO_ERROR; case NPNVxtAppContext: @@ -395,7 +638,8 @@ NPError PluginView::getValue(NPNVariable variable, void* value) case NPNVnetscapeWindow: { void* w = reinterpret_cast<void*>(value); - *((XID *)w) = m_parentFrame->view()->hostWindow()->platformWindow()->winId(); + QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient(); + *((XID *)w) = client ? client->ownerWidget()->window()->winId() : 0; return NPERR_NO_ERROR; } @@ -412,7 +656,7 @@ NPError PluginView::getValue(NPNVariable variable, void* value) void PluginView::invalidateRect(const IntRect& rect) { - if (platformWidget()) { + if (m_isWindowed) { platformWidget()->update(rect); return; } @@ -422,59 +666,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); @@ -485,36 +764,92 @@ void PluginView::init() PluginView::setCurrentPluginView(0); } - if (m_needsXEmbed) { - setPlatformWidget(new PluginContainerQt(this, m_parentFrame->view()->hostWindow()->platformWindow())); + if (m_isWindowed) { + QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient(); + if (m_needsXEmbed && client) { + setPlatformWidget(new PluginContainerQt(this, client->ownerWidget())); + // 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; + } - m_npWindow.type = NPWindowTypeWindow; - m_npWindow.window = (void*)platformPluginWidget()->winId(); - m_npWindow.width = -1; - m_npWindow.height = -1; + 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 = 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::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/src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.cpp b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.cpp new file mode 100644 index 000000000..aece0e48b --- /dev/null +++ b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.cpp @@ -0,0 +1,77 @@ +/* + 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. +*/ + +#include "config.h" +#include "PluginContainerSymbian.h" + +#include "FocusController.h" +#include "Frame.h" +#include "FrameView.h" +#include "Page.h" +#include "PlatformKeyboardEvent.h" +#include "PluginView.h" + +#include <QApplication> +#include <QWidget> + +using namespace WebCore; + +PluginContainerSymbian::PluginContainerSymbian(PluginView* view, QWidget* parent) + : m_parent(parent) + , m_pluginView(view) + , m_hasPendingGeometryChange(false) +{ + setParent(m_parent); +} + +PluginContainerSymbian::~PluginContainerSymbian() +{ +} + +void PluginContainerSymbian::requestGeometry(const QRect& rect, const QRegion& clip) +{ + if (m_windowRect != rect || m_clipRegion != clip) { + m_windowRect = rect; + m_clipRegion = clip; + m_hasPendingGeometryChange = true; + } +} + +void PluginContainerSymbian::adjustGeometry() +{ + if (m_hasPendingGeometryChange) { + setGeometry(m_windowRect); + setMask(m_clipRegion); + m_hasPendingGeometryChange = false; + } +} + +void PluginContainerSymbian::focusInEvent(QFocusEvent* event) +{ + if (Page* page = m_pluginView->parentFrame()->page()) + page->focusController()->setActive(true); + + m_pluginView->focusPluginElement(); +} + +void PluginContainerSymbian::focusOutEvent(QFocusEvent*) +{ + if (Page* page = m_pluginView->parentFrame()->page()) + page->focusController()->setActive(false); +} diff --git a/src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.h b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.h new file mode 100644 index 000000000..fce4a7160 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.h @@ -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. +*/ + +#ifndef PluginContainerSymbian_h +#define PluginContainerSymbian_h + +#include <QWidget> + +namespace WebCore { + + class PluginView; + + class PluginContainerSymbian : public QWidget { + Q_OBJECT + public: + PluginContainerSymbian(PluginView*, QWidget* parent); + ~PluginContainerSymbian(); + + void requestGeometry(const QRect&, const QRegion& clip = QRegion()); + void adjustGeometry(); + + protected: + virtual void focusInEvent(QFocusEvent*); + virtual void focusOutEvent(QFocusEvent*); + private: + PluginView* m_pluginView; + QWidget* m_parent; + QRect m_windowRect; + QRegion m_clipRegion; + bool m_hasPendingGeometryChange; + }; +} + +#endif // PluginContainerSymbian_h diff --git a/src/3rdparty/webkit/WebCore/plugins/symbian/PluginDatabaseSymbian.cpp b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginDatabaseSymbian.cpp new file mode 100644 index 000000000..2e092966e --- /dev/null +++ b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginDatabaseSymbian.cpp @@ -0,0 +1,79 @@ +/* + 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. +*/ +#include "config.h" +#include "PluginDatabase.h" + +#include <QFileInfo> +#include <f32file.h> + +static const char QTPLUGIN_FILTER[] = "*.qtplugin"; +static const char QT_PLUGIN_FOLDER[] = ":\\resource\\qt\\plugins\\npqtplugins\\"; + +namespace WebCore { + +Vector<String> PluginDatabase::defaultPluginDirectories() +{ + Vector<String> directories; + //find the installation drive + TDriveList drivelist; + TChar driveLetter; + RFs fsSession; + + if (fsSession.Connect() == KErrNone && fsSession.DriveList(drivelist) == KErrNone) { + for (TInt driveNumber = EDriveA; driveNumber <= EDriveZ; driveNumber++) { + if (drivelist[driveNumber] && fsSession.DriveToChar(driveNumber, driveLetter) == KErrNone) { + QString driveStringValue(QChar((uint)driveLetter.GetUpperCase())); + QString stubDirPath; + stubDirPath.append(driveStringValue); + stubDirPath.append(QT_PLUGIN_FOLDER); + if (QFileInfo(stubDirPath).exists()) + directories.append(stubDirPath); + } + } + } + + fsSession.Close(); + return directories; +} + +bool PluginDatabase::isPreferredPluginDirectory(const String& path) +{ + return true; +} + +void PluginDatabase::getPluginPathsInDirectories(HashSet<String>& paths) const +{ + // FIXME: This should be a case insensitive set. + HashSet<String> uniqueFilenames; + + String fileNameFilter(QTPLUGIN_FILTER); + + Vector<String>::const_iterator dirsEnd = m_pluginDirectories.end(); + for (Vector<String>::const_iterator dIt = m_pluginDirectories.begin(); dIt != dirsEnd; ++dIt) { + Vector<String> pluginPaths = listDirectory(*dIt, fileNameFilter); + Vector<String>::const_iterator pluginsEnd = pluginPaths.end(); + for (Vector<String>::const_iterator pIt = pluginPaths.begin(); pIt != pluginsEnd; ++pIt) { + if (!fileExists(*pIt)) + continue; + paths.add(*pIt); + } + } +} + +} diff --git a/src/3rdparty/webkit/WebCore/plugins/symbian/PluginPackageSymbian.cpp b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginPackageSymbian.cpp new file mode 100644 index 000000000..d5c7533f6 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginPackageSymbian.cpp @@ -0,0 +1,177 @@ +/* + 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. +*/ +#include "config.h" +#include "PluginPackage.h" + +#include "CString.h" +#include "MIMETypeRegistry.h" +#include "npinterface.h" +#include "npruntime_impl.h" +#include "PluginDatabase.h" +#include "PluginDebug.h" +#include <QPluginLoader> + +namespace WebCore { + +bool PluginPackage::fetchInfo() +{ + if (!load()) + return false; + + char* buf = 0; + NPError err = m_pluginFuncs.getvalue(0, NPPVpluginNameString, (void *)&buf); + m_name = buf; + err = m_pluginFuncs.getvalue(0, NPPVpluginDescriptionString, (void *)&buf); + m_description = buf; + + determineModuleVersionFromDescription(); + + String s = m_npInterface->NP_GetMIMEDescription(); + Vector<String> types; + s.split(UChar('|'), false, types); // <MIME1>;<ext1,ext2,ext3,...>;<Description>|<MIME2>|<MIME3>|... + + for (int i = 0; i < types.size(); ++i) { + Vector<String> mime; + types[i].split(UChar(';'), true, mime); // <MIME1>;<ext1,ext2,ext3,...>;<Description> + if (mime.size() > 0) { + Vector<String> exts; + if (mime.size() > 1) + mime[1].split(UChar(','), false, exts); // <ext1,ext2,ext3,...> + + m_mimeToExtensions.add(mime[0], exts); // <MIME>,<ext1,ext2,ext3> + if (mime.size() > 2) + m_mimeToDescriptions.add(mime[0], mime[2]); // <MIME>,<Description> + } + } + unload(); + return true; +} + +bool PluginPackage::load() +{ + if (m_isLoaded) { + m_loadCount++; + return true; + } + + m_pluginLoader = new QPluginLoader(m_path); + if (!m_pluginLoader->load()) { + delete m_pluginLoader; + m_pluginLoader = 0; + return false; + } + + QObject* plugin = m_pluginLoader->instance(); + if (!plugin) { + m_pluginLoader->unload(); + delete m_pluginLoader; + m_pluginLoader = 0; + return false; + } + + // Plugin instance created + // Cast plugin to NPInterface, + m_npInterface = qobject_cast<NPInterface*>(plugin); + if (!m_npInterface) { + m_pluginLoader->unload(); + delete m_pluginLoader; + m_pluginLoader = 0; + return false; + } + + m_isLoaded = true; + + NPError npErr; + memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs)); + m_pluginFuncs.size = sizeof(m_pluginFuncs); + m_browserFuncs.size = sizeof(m_browserFuncs); + m_browserFuncs.version = NP_VERSION_MINOR; + m_browserFuncs.geturl = NPN_GetURL; + m_browserFuncs.posturl = NPN_PostURL; + m_browserFuncs.requestread = NPN_RequestRead; + m_browserFuncs.newstream = NPN_NewStream; + m_browserFuncs.write = NPN_Write; + m_browserFuncs.destroystream = NPN_DestroyStream; + m_browserFuncs.status = NPN_Status; + m_browserFuncs.uagent = NPN_UserAgent; + m_browserFuncs.memalloc = NPN_MemAlloc; + m_browserFuncs.memfree = NPN_MemFree; + m_browserFuncs.memflush = NPN_MemFlush; + m_browserFuncs.reloadplugins = NPN_ReloadPlugins; + m_browserFuncs.geturlnotify = NPN_GetURLNotify; + m_browserFuncs.posturlnotify = NPN_PostURLNotify; + m_browserFuncs.getvalue = NPN_GetValue; + m_browserFuncs.setvalue = NPN_SetValue; + m_browserFuncs.invalidaterect = NPN_InvalidateRect; + m_browserFuncs.invalidateregion = NPN_InvalidateRegion; + m_browserFuncs.forceredraw = NPN_ForceRedraw; + m_browserFuncs.getJavaEnv = NPN_GetJavaEnv; + m_browserFuncs.getJavaPeer = NPN_GetJavaPeer; + m_browserFuncs.pushpopupsenabledstate = NPN_PushPopupsEnabledState; + m_browserFuncs.poppopupsenabledstate = NPN_PopPopupsEnabledState; + m_browserFuncs.releasevariantvalue = _NPN_ReleaseVariantValue; + m_browserFuncs.getstringidentifier = _NPN_GetStringIdentifier; + m_browserFuncs.getstringidentifiers = _NPN_GetStringIdentifiers; + m_browserFuncs.getintidentifier = _NPN_GetIntIdentifier; + m_browserFuncs.identifierisstring = _NPN_IdentifierIsString; + m_browserFuncs.utf8fromidentifier = _NPN_UTF8FromIdentifier; + m_browserFuncs.createobject = _NPN_CreateObject; + m_browserFuncs.retainobject = _NPN_RetainObject; + m_browserFuncs.releaseobject = _NPN_ReleaseObject; + m_browserFuncs.invoke = _NPN_Invoke; + m_browserFuncs.invokeDefault = _NPN_InvokeDefault; + m_browserFuncs.evaluate = _NPN_Evaluate; + m_browserFuncs.getproperty = _NPN_GetProperty; + m_browserFuncs.setproperty = _NPN_SetProperty; + m_browserFuncs.removeproperty = _NPN_RemoveProperty; + m_browserFuncs.hasproperty = _NPN_HasMethod; + m_browserFuncs.hasmethod = _NPN_HasProperty; + m_browserFuncs.setexception = _NPN_SetException; + m_browserFuncs.enumerate = _NPN_Enumerate; + m_browserFuncs.construct = _NPN_Construct; + + npErr = m_npInterface->NP_Initialize(&m_browserFuncs, &m_pluginFuncs); + if (npErr != NPERR_NO_ERROR) { + m_pluginLoader->unload(); + delete m_pluginLoader; + m_pluginLoader = 0; + return false; + } + + m_loadCount++; + return true; +} + +void PluginPackage::unload() +{ + if (!m_isLoaded) + return; + + if (--m_loadCount > 0) + return; + + m_isLoaded = false; + m_npInterface->NP_Shutdown(); + + m_pluginLoader->unload(); + delete m_pluginLoader; + m_pluginLoader = 0; +} +} + diff --git a/src/3rdparty/webkit/WebCore/plugins/symbian/PluginViewSymbian.cpp b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginViewSymbian.cpp new file mode 100644 index 000000000..14e25b1d1 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginViewSymbian.cpp @@ -0,0 +1,462 @@ +/* + 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. +*/ +#include "config.h" +#include "PluginView.h" + +#include "Document.h" +#include "DocumentLoader.h" +#include "Element.h" +#include "FocusController.h" +#include "Frame.h" +#include "FrameLoadRequest.h" +#include "FrameLoader.h" +#include "FrameTree.h" +#include "FrameView.h" +#include "GraphicsContext.h" +#include "HTMLNames.h" +#include "HTMLPlugInElement.h" +#include "Image.h" +#include "JSDOMBinding.h" +#include "KeyboardEvent.h" +#include "MouseEvent.h" +#include "NotImplemented.h" +#include "npfunctions.h" +#include "npinterface.h" +#include "Page.h" +#include "PlatformKeyboardEvent.h" +#include "PlatformMouseEvent.h" +#include "PluginContainerSymbian.h" +#include "PluginDebug.h" +#include "PluginMainThreadScheduler.h" +#include "PluginPackage.h" +#include "RenderLayer.h" +#include "ScriptController.h" +#include "Settings.h" +#include "npruntime_impl.h" +#include "runtime.h" +#include "runtime_root.h" +#include "QWebPageClient.h" +#include <QKeyEvent> +#include <QPixmap.h> +#include <QRegion> +#include <QVector> +#include <QWidget> +#include <runtime/JSLock.h> +#include <runtime/JSValue.h> + +using JSC::ExecState; +using JSC::Interpreter; +using JSC::JSLock; +using JSC::JSObject; +using JSC::UString; + +using namespace std; + +using namespace WTF; + +namespace WebCore { + +using namespace HTMLNames; + +void PluginView::updatePluginWidget() +{ + if (!parent()) + return; + ASSERT(parent()->isFrameView()); + FrameView* frameView = static_cast<FrameView*>(parent()); + IntRect oldWindowRect = m_windowRect; + IntRect oldClipRect = m_clipRect; + + m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size()); + m_clipRect = windowClipRect(); + m_clipRect.move(-m_windowRect.x(), -m_windowRect.y()); + if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect) + return; + + // in order to move/resize the plugin window at the same time as the rest of frame + // during e.g. scrolling, we set the mask and geometry in the paint() function, but + // as paint() isn't called when the plugin window is outside the frame which can + // be caused by a scroll, we need to move/resize immediately. + if (!m_windowRect.intersects(frameView->frameRect())) + setNPWindowIfNeeded(); +} + +void PluginView::setFocus() +{ + if (platformPluginWidget()) + platformPluginWidget()->setFocus(Qt::OtherFocusReason); + else + Widget::setFocus(); +} + +void PluginView::show() +{ + setSelfVisible(true); + + if (isParentVisible() && platformPluginWidget()) + platformPluginWidget()->setVisible(true); +} + +void PluginView::hide() +{ + setSelfVisible(false); + + if (isParentVisible() && platformPluginWidget()) + platformPluginWidget()->setVisible(false); +} + +void PluginView::paint(GraphicsContext* context, const IntRect& rect) +{ + if (!m_isStarted) { + paintMissingPluginIcon(context, rect); + return; + } + + if (context->paintingDisabled()) + return; + m_npWindow.ws_info = (void*)(context->platformContext()); + setNPWindowIfNeeded(); + + if (m_isWindowed && platformPluginWidget()) + static_cast<PluginContainerSymbian*>(platformPluginWidget())->adjustGeometry(); + + if (m_isWindowed) + return; + + context->save(); + IntRect clipRect(rect); + clipRect.intersect(frameRect()); + context->clip(clipRect); + context->translate(frameRect().location().x(), frameRect().location().y()); + + QPaintEvent ev(rect); + QEvent& npEvent = ev; + dispatchNPEvent(npEvent); + + context->restore(); +} + +// TODO: Unify across ports. +bool PluginView::dispatchNPEvent(NPEvent& event) +{ + if (!m_plugin->pluginFuncs()->event) + return false; + + PluginView::setCurrentPluginView(this); + JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); + + setCallingPlugin(true); + bool accepted = m_plugin->pluginFuncs()->event(m_instance, &event); + setCallingPlugin(false); + PluginView::setCurrentPluginView(0); + + return accepted; +} + +void PluginView::handleKeyboardEvent(KeyboardEvent* event) +{ + if (m_isWindowed) + return; + + QEvent& npEvent = *(event->keyEvent()->qtEvent()); + if (!dispatchNPEvent(npEvent)) + event->setDefaultHandled(); +} + +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(); + } + + QEvent::Type type; + if (event->type() == eventNames().mousedownEvent) + type = QEvent::MouseButtonPress; + else if (event->type() == eventNames().mousemoveEvent) + type = QEvent::MouseMove; + else if (event->type() == eventNames().mouseupEvent) + type = QEvent::MouseButtonRelease; + else + return; + + QPoint position(event->offsetX(), event->offsetY()); + Qt::MouseButton button; + switch (event->which()) { + case 1: + button = Qt::LeftButton; + break; + case 2: + button = Qt::MidButton; + break; + case 3: + button = Qt::RightButton; + break; + default: + button = Qt::NoButton; + } + Qt::KeyboardModifiers modifiers = 0; + if (event->ctrlKey()) + modifiers |= Qt::ControlModifier; + if (event->altKey()) + modifiers |= Qt::AltModifier; + if (event->shiftKey()) + modifiers |= Qt::ShiftModifier; + if (event->metaKey()) + modifiers |= Qt::MetaModifier; + QMouseEvent mouseEvent(type, position, button, button, modifiers); + QEvent& npEvent = mouseEvent; + if (!dispatchNPEvent(npEvent)) + event->setDefaultHandled(); +} + +void PluginView::setParent(ScrollView* parent) +{ + Widget::setParent(parent); + + if (parent) + init(); +} + +void PluginView::setNPWindowRect(const IntRect&) +{ + if (!m_isWindowed) + setNPWindowIfNeeded(); +} + +void PluginView::setNPWindowIfNeeded() +{ + if (!m_isStarted || !parent() || !m_plugin->pluginFuncs()->setwindow) + return; + 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 { + // always call this method before painting. + m_npWindow.x = 0; + m_npWindow.y = 0; + + m_npWindow.clipRect.left = 0; + m_npWindow.clipRect.top = 0; + m_npWindow.clipRect.right = m_windowRect.width(); + m_npWindow.clipRect.bottom = m_windowRect.height(); + m_npWindow.window = 0; + } + + m_npWindow.width = m_windowRect.width(); + m_npWindow.height = m_windowRect.height(); + if (m_npWindow.x < 0 || m_npWindow.y < 0 || m_npWindow.width <= 0 || m_npWindow.height <= 0) + return; + + PluginView::setCurrentPluginView(this); + JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); + setCallingPlugin(true); + m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow); + setCallingPlugin(false); + PluginView::setCurrentPluginView(0); +} + +void PluginView::setParentVisible(bool visible) +{ + if (isParentVisible() == visible) + return; + + Widget::setParentVisible(visible); + + if (isSelfVisible() && platformPluginWidget()) + platformPluginWidget()->setVisible(visible); +} + +NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf) +{ + notImplemented(); + return NPERR_NO_ERROR; +} + +NPError PluginView::getValueStatic(NPNVariable variable, void* value) +{ + LOG(Plugins, "PluginView::getValueStatic(%s)", prettyNameForNPNVariable(variable).data()); + + switch (variable) { + case NPNVjavascriptEnabledBool: + *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; + } +} + +NPError PluginView::getValue(NPNVariable variable, void* value) +{ + LOG(Plugins, "PluginView::getValue(%s)", prettyNameForNPNVariable(variable).data()); + + switch (variable) { + case NPNVWindowNPObject: { + if (m_isJavaScriptPaused) + return NPERR_GENERIC_ERROR; + + NPObject* windowScriptObject = m_parentFrame->script()->windowScriptNPObject(); + + // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugin/npruntime.html> + if (windowScriptObject) + _NPN_RetainObject(windowScriptObject); + + void** v = (void**)value; + *v = windowScriptObject; + + return NPERR_NO_ERROR; + } + + case NPNVPluginElementNPObject: { + if (m_isJavaScriptPaused) + return NPERR_GENERIC_ERROR; + + NPObject* pluginScriptObject = 0; + + if (m_element->hasTagName(appletTag) || m_element->hasTagName(embedTag) || m_element->hasTagName(objectTag)) + pluginScriptObject = static_cast<HTMLPlugInElement*>(m_element)->getNPObject(); + + // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugin/npruntime.html> + if (pluginScriptObject) + _NPN_RetainObject(pluginScriptObject); + + void** v = (void**)value; + *v = pluginScriptObject; + + return NPERR_NO_ERROR; + } + default: + return getValueStatic(variable, value); + } +} + +void PluginView::invalidateRect(const IntRect& rect) +{ + if (m_isWindowed) { + platformWidget()->update(rect); + return; + } + + invalidateWindowlessPluginRect(rect); +} + +void PluginView::invalidateRect(NPRect* rect) +{ + if (m_isWindowed) + return; + if (!rect) { + invalidate(); + return; + } + IntRect r(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top); + m_invalidRects.append(r); + if (!m_invalidateTimer.isActive()) + m_invalidateTimer.startOneShot(0.001); +} + +void PluginView::invalidateRegion(NPRegion region) +{ + if (m_isWindowed) + return; + + if (!region) + return; + + QVector<QRect> rects = region->rects(); + for (int i = 0; i < rects.size(); ++i) { + const QRect& qRect = rects.at(i); + m_invalidRects.append(qRect); + if (!m_invalidateTimer.isActive()) + m_invalidateTimer.startOneShot(0.001); + } +} + +void PluginView::forceRedraw() +{ + if (m_isWindowed) + return; + invalidate(); +} + +bool PluginView::platformStart() +{ + ASSERT(m_isStarted); + ASSERT(m_status == PluginStatusLoadedSuccessfully); + + show(); + + if (m_isWindowed) { + QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient(); + // FIXME this will not work for QGraphicsView. + // But we cannot use winId because it will create a window and on S60, + // QWidgets should not create a window. + Q_ASSERT(qobject_cast<QWidget*>(client->pluginParent())); + setPlatformWidget(new PluginContainerSymbian(this, + qobject_cast<QWidget*>(client->pluginParent()))); + m_npWindow.type = NPWindowTypeWindow; + m_npWindow.window = (void*)platformPluginWidget(); + + } else { + setPlatformWidget(0); + m_npWindow.type = NPWindowTypeDrawable; + m_npWindow.window = 0; // Not used? + } + setNPWindowIfNeeded(); + + return true; +} + +void PluginView::platformDestroy() +{ + delete platformPluginWidget(); +} + +void PluginView::halt() +{ +} + +void PluginView::restart() +{ +} + +} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/plugins/symbian/npinterface.h b/src/3rdparty/webkit/WebCore/plugins/symbian/npinterface.h new file mode 100644 index 000000000..0f0b6ca22 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/plugins/symbian/npinterface.h @@ -0,0 +1,37 @@ +/* + 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. +*/ +#ifndef npinterface_H +#define npinterface_H + +#include "npfunctions.h" +#include <QtPlugin> + +class NPInterface { +public: + virtual NPError NP_Initialize(NPNetscapeFuncs* aNPNFuncs, NPPluginFuncs* aNPPFuncs) = 0; + virtual void NP_Shutdown() = 0; + virtual char* NP_GetMIMEDescription() = 0; +}; + + +QT_BEGIN_NAMESPACE +Q_DECLARE_INTERFACE(NPInterface, "com.nokia.qts60.webplugin/1.0"); +QT_END_NAMESPACE + +#endif // npinterface_H diff --git a/src/3rdparty/webkit/WebCore/plugins/win/PluginPackageWin.cpp b/src/3rdparty/webkit/WebCore/plugins/win/PluginPackageWin.cpp index 9e38925c8..dc9ec17bd 100644 --- a/src/3rdparty/webkit/WebCore/plugins/win/PluginPackageWin.cpp +++ b/src/3rdparty/webkit/WebCore/plugins/win/PluginPackageWin.cpp @@ -56,17 +56,6 @@ static String getVersionInfo(const LPVOID versionInfoData, const String& info) return String(reinterpret_cast<UChar*>(buffer), bufferLength - 1); } -int PluginPackage::compareFileVersion(const PlatformModuleVersion& compareVersion) const -{ - // return -1, 0, or 1 if plug-in version is less than, equal to, or greater than - // the passed version - if (m_moduleVersion.mostSig != compareVersion.mostSig) - return m_moduleVersion.mostSig > compareVersion.mostSig ? 1 : -1; - if (m_moduleVersion.leastSig != compareVersion.leastSig) - return m_moduleVersion.leastSig > compareVersion.leastSig ? 1 : -1; - return 0; -} - bool PluginPackage::isPluginBlacklisted() { if (name() == "Citrix ICA Client") { @@ -245,7 +234,9 @@ bool PluginPackage::load() m_loadCount++; return true; } else { -#if !PLATFORM(WINCE) +#if PLATFORM(WINCE) + m_module = ::LoadLibraryW(m_path.charactersWithNullTermination()); +#else WCHAR currentPath[MAX_PATH]; if (!::GetCurrentDirectoryW(MAX_PATH, currentPath)) @@ -255,12 +246,10 @@ bool PluginPackage::load() if (!::SetCurrentDirectoryW(path.charactersWithNullTermination())) return false; -#endif // Load the library m_module = ::LoadLibraryExW(m_path.charactersWithNullTermination(), 0, LOAD_WITH_ALTERED_SEARCH_PATH); -#if !PLATFORM(WINCE) if (!::SetCurrentDirectoryW(currentPath)) { if (m_module) ::FreeLibrary(m_module); diff --git a/src/3rdparty/webkit/WebCore/plugins/win/PluginViewWin.cpp b/src/3rdparty/webkit/WebCore/plugins/win/PluginViewWin.cpp index 268718643..b313afbc0 100644 --- a/src/3rdparty/webkit/WebCore/plugins/win/PluginViewWin.cpp +++ b/src/3rdparty/webkit/WebCore/plugins/win/PluginViewWin.cpp @@ -29,6 +29,8 @@ #include "PluginView.h" +#include "BitmapImage.h" +#include "BitmapInfo.h" #include "Document.h" #include "DocumentLoader.h" #include "Element.h" @@ -52,6 +54,7 @@ #include "PluginMessageThrottlerWin.h" #include "PluginPackage.h" #include "PluginMainThreadScheduler.h" +#include "RenderWidget.h" #include "JSDOMBinding.h" #include "ScriptController.h" #include "PluginDatabase.h" @@ -74,17 +77,18 @@ #endif #if PLATFORM(QT) -#include <QWidget.h> +#include "QWebPageClient.h" +#include <QWidget> #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->ownerWidget()->winId(); #else - return widget; + return client; #endif } @@ -104,8 +108,6 @@ using namespace HTMLNames; const LPCWSTR kWebPluginViewdowClassName = L"WebPluginView"; const LPCWSTR kWebPluginViewProperty = L"WebPluginViewProperty"; -static const char* MozillaUserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0"; - #if !PLATFORM(WINCE) // The code used to hook BeginPaint/EndPaint originally came from // <http://www.fengyuan.com/article/wmprint.html>. @@ -143,7 +145,7 @@ HDC WINAPI PluginView::hookedBeginPaint(HWND hWnd, PAINTSTRUCT* lpPaint) "push %3\n" "call *%4\n" : "=a" (result) - : "a" (beginPaintSysCall), "g" (lpPaint), "g" (hWnd), "m" (*beginPaint) + : "a" (beginPaintSysCall), "g" (lpPaint), "g" (hWnd), "m" (beginPaint) : "memory" ); return result; @@ -173,7 +175,7 @@ BOOL WINAPI PluginView::hookedEndPaint(HWND hWnd, const PAINTSTRUCT* lpPaint) "push %3\n" "call *%4\n" : "=a" (result) - : "a" (endPaintSysCall), "g" (lpPaint), "g" (hWnd), "m" (*endPaint) + : "a" (endPaintSysCall), "g" (lpPaint), "g" (hWnd), "m" (endPaint) ); return result; #elif defined (_M_IX86) @@ -411,7 +413,7 @@ void PluginView::updatePluginWidget() m_clipRect = windowClipRect(); m_clipRect.move(-m_windowRect.x(), -m_windowRect.y()); - if (platformPluginWidget() && (m_windowRect != oldWindowRect || m_clipRect != oldClipRect)) { + if (platformPluginWidget() && (!m_haveUpdatedPluginWidget || m_windowRect != oldWindowRect || m_clipRect != oldClipRect)) { HRGN rgn; setCallingPlugin(true); @@ -429,7 +431,7 @@ void PluginView::updatePluginWidget() ::SetWindowRgn(platformPluginWidget(), rgn, TRUE); } - if (m_windowRect != oldWindowRect) + if (!m_haveUpdatedPluginWidget || m_windowRect != oldWindowRect) ::MoveWindow(platformPluginWidget(), m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height(), TRUE); if (clipToZeroRect) { @@ -438,6 +440,8 @@ void PluginView::updatePluginWidget() } setCallingPlugin(false); + + m_haveUpdatedPluginWidget = true; } } @@ -492,7 +496,54 @@ bool PluginView::dispatchNPEvent(NPEvent& npEvent) return result; } -void PluginView::paintWindowedPluginIntoContext(GraphicsContext* context, const IntRect& rect) const +void PluginView::paintIntoTransformedContext(HDC hdc) +{ + if (m_isWindowed) { + SendMessage(platformPluginWidget(), WM_PRINTCLIENT, reinterpret_cast<WPARAM>(hdc), PRF_CLIENT | PRF_CHILDREN | PRF_OWNED); + return; + } + + m_npWindow.type = NPWindowTypeDrawable; + m_npWindow.window = hdc; + + WINDOWPOS windowpos = { 0 }; + +#if PLATFORM(WINCE) + IntRect r = static_cast<FrameView*>(parent())->contentsToWindow(frameRect()); + + windowpos.x = r.x(); + windowpos.y = r.y(); + windowpos.cx = r.width(); + windowpos.cy = r.height(); +#else + IntPoint p = static_cast<FrameView*>(parent())->contentsToWindow(frameRect().location()); + + windowpos.x = p.x(); + windowpos.y = p.y(); + windowpos.cx = frameRect().width(); + windowpos.cy = frameRect().height(); +#endif + + NPEvent npEvent; + npEvent.event = WM_WINDOWPOSCHANGED; + npEvent.lParam = reinterpret_cast<uint32>(&windowpos); + npEvent.wParam = 0; + + dispatchNPEvent(npEvent); + + setNPWindowRect(frameRect()); + + npEvent.event = WM_PAINT; + npEvent.wParam = reinterpret_cast<uint32>(hdc); + + // This is supposed to be a pointer to the dirty rect, but it seems that the Flash plugin + // ignores it so we just pass null. + npEvent.lParam = 0; + + dispatchNPEvent(npEvent); +} + +void PluginView::paintWindowedPluginIntoContext(GraphicsContext* context, const IntRect& rect) { #if !PLATFORM(WINCE) ASSERT(m_isWindowed); @@ -514,7 +565,7 @@ void PluginView::paintWindowedPluginIntoContext(GraphicsContext* context, const SetWorldTransform(hdc, &transform); - SendMessage(platformPluginWidget(), WM_PRINTCLIENT, reinterpret_cast<WPARAM>(hdc), PRF_CLIENT | PRF_CHILDREN | PRF_OWNED); + paintIntoTransformedContext(hdc); SetWorldTransform(hdc, &originalTransform); @@ -544,7 +595,6 @@ void PluginView::paint(GraphicsContext* context, const IntRect& rect) ASSERT(parent()->isFrameView()); IntRect rectInWindow = static_cast<FrameView*>(parent())->contentsToWindow(frameRect()); HDC hdc = context->getWindowsContext(rectInWindow, m_isTransparent); - NPEvent npEvent; // On Safari/Windows without transparency layers the GraphicsContext returns the HDC // of the window and the plugin expects that the passed in DC has window coordinates. @@ -560,44 +610,7 @@ void PluginView::paint(GraphicsContext* context, const IntRect& rect) } #endif - m_npWindow.type = NPWindowTypeDrawable; - m_npWindow.window = hdc; - - WINDOWPOS windowpos; - memset(&windowpos, 0, sizeof(windowpos)); - -#if PLATFORM(WINCE) - IntRect r = static_cast<FrameView*>(parent())->contentsToWindow(frameRect()); - - windowpos.x = r.x(); - windowpos.y = r.y(); - windowpos.cx = r.width(); - windowpos.cy = r.height(); -#else - IntPoint p = static_cast<FrameView*>(parent())->contentsToWindow(frameRect().location()); - - windowpos.x = p.x(); - windowpos.y = p.y(); - windowpos.cx = frameRect().width(); - windowpos.cy = frameRect().height(); -#endif - - npEvent.event = WM_WINDOWPOSCHANGED; - npEvent.lParam = reinterpret_cast<uint32>(&windowpos); - npEvent.wParam = 0; - - dispatchNPEvent(npEvent); - - setNPWindowRect(frameRect()); - - npEvent.event = WM_PAINT; - npEvent.wParam = reinterpret_cast<uint32>(hdc); - - // This is supposed to be a pointer to the dirty rect, but it seems that the Flash plugin - // ignores it so we just pass null. - npEvent.lParam = 0; - - dispatchNPEvent(npEvent); + paintIntoTransformedContext(hdc); context->releaseWindowsContext(hdc, frameRect(), m_isTransparent); } @@ -795,80 +808,6 @@ void PluginView::setNPWindowRect(const IntRect& rect) } } -void PluginView::stop() -{ - if (!m_isStarted) - return; - - HashSet<RefPtr<PluginStream> > streams = m_streams; - HashSet<RefPtr<PluginStream> >::iterator end = streams.end(); - for (HashSet<RefPtr<PluginStream> >::iterator it = streams.begin(); it != end; ++it) { - (*it)->stop(); - disconnectStream((*it).get()); - } - - ASSERT(m_streams.isEmpty()); - - m_isStarted = false; - - // Unsubclass the window - if (m_isWindowed) { -#if PLATFORM(WINCE) - WNDPROC currentWndProc = (WNDPROC)GetWindowLong(platformPluginWidget(), GWL_WNDPROC); - - if (currentWndProc == PluginViewWndProc) - SetWindowLong(platformPluginWidget(), GWL_WNDPROC, (LONG)m_pluginWndProc); -#else - WNDPROC currentWndProc = (WNDPROC)GetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC); - - if (currentWndProc == PluginViewWndProc) - SetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC, (LONG)m_pluginWndProc); -#endif - } - - JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); - - // Clear the window - m_npWindow.window = 0; - if (m_plugin->pluginFuncs()->setwindow && !m_plugin->quirks().contains(PluginQuirkDontSetNullWindowHandleOnDestroy)) { - setCallingPlugin(true); - m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow); - setCallingPlugin(false); - } - - PluginMainThreadScheduler::scheduler().unregisterPlugin(m_instance); - - // Destroy the plugin - NPSavedData* savedData = 0; - setCallingPlugin(true); - NPError npErr = m_plugin->pluginFuncs()->destroy(m_instance, &savedData); - setCallingPlugin(false); - LOG_NPERROR(npErr); - - if (savedData) { - if (savedData->buf) - NPN_MemFree(savedData->buf); - NPN_MemFree(savedData); - } - - m_instance->pdata = 0; -} - -const char* PluginView::userAgentStatic() -{ - return 0; -} - -const char* PluginView::userAgent() -{ - if (m_plugin->quirks().contains(PluginQuirkWantsMozillaUserAgent)) - return MozillaUserAgent; - - if (m_userAgent.isNull()) - m_userAgent = m_parentFrame->loader()->userAgent(m_url).utf8(); - return m_userAgent.data(); -} - NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf) { String filename(buf, len); @@ -954,7 +893,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; } @@ -1026,50 +965,13 @@ void PluginView::forceRedraw() if (m_isWindowed) ::UpdateWindow(platformPluginWidget()); else - ::UpdateWindow(windowHandleForPlatformWidget(parent() ? parent()->hostWindow()->platformWindow() : 0)); -} - -PluginView::~PluginView() -{ - if (m_instance) - m_instance->ndata = 0; - 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() +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_isWindowed) { registerPluginView(); @@ -1081,7 +983,7 @@ void PluginView::init() 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); @@ -1109,10 +1011,84 @@ void PluginView::init() m_npWindow.window = 0; } + updatePluginWidget(); + if (!m_plugin->quirks().contains(PluginQuirkDeferFirstSetWindowCall)) setNPWindowRect(frameRect()); - m_status = PluginStatusLoadedSuccessfully; + return true; +} + +void PluginView::platformDestroy() +{ + if (!platformPluginWidget()) + return; + + DestroyWindow(platformPluginWidget()); + setPlatformPluginWidget(0); +} + +PassRefPtr<Image> PluginView::snapshot() +{ + OwnPtr<HDC> hdc(CreateCompatibleDC(0)); + + if (!m_isWindowed) { + // Enable world transforms. + SetGraphicsMode(hdc.get(), GM_ADVANCED); + + XFORM transform; + GetWorldTransform(hdc.get(), &transform); + + // Windowless plug-ins assume that they're drawing onto the view's DC. + // Translate the context so that the plug-in draws at (0, 0). + ASSERT(parent()->isFrameView()); + IntPoint position = static_cast<FrameView*>(parent())->contentsToWindow(frameRect()).location(); + transform.eDx = -position.x(); + transform.eDy = -position.y(); + SetWorldTransform(hdc.get(), &transform); + } + + void* bits; + BitmapInfo bmp = BitmapInfo::createBottomUp(frameRect().size()); + OwnPtr<HBITMAP> hbmp(CreateDIBSection(0, &bmp, DIB_RGB_COLORS, &bits, 0, 0)); + + HBITMAP hbmpOld = static_cast<HBITMAP>(SelectObject(hdc.get(), hbmp.get())); + + paintIntoTransformedContext(hdc.get()); + + SelectObject(hdc.get(), hbmpOld); + + return BitmapImage::create(hbmp.get()); +} + +void PluginView::halt() +{ + ASSERT(!m_isHalted); + ASSERT(m_isStarted); + +#if !PLATFORM(QT) + // Show a screenshot of the plug-in. + toRenderWidget(m_element->renderer())->showSubstituteImage(snapshot()); +#endif + + m_isHalted = true; + m_hasBeenHalted = true; + + stop(); + platformDestroy(); +} + +void PluginView::restart() +{ + ASSERT(!m_isStarted); + ASSERT(m_isHalted); + + // Clear any substitute image. + toRenderWidget(m_element->renderer())->showSubstituteImage(0); + + m_isHalted = false; + m_haveUpdatedPluginWidget = false; + start(); } } // namespace WebCore |