summaryrefslogtreecommitdiffstats
path: root/WebCore/plugins
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commit9364f22aed35e1a1e9d07c121510f80be3ab0502 (patch)
treed49911209b132da58d838efa852daf28d516df21 /WebCore/plugins
parent87eb0cb35bad8784770ebc807e6c982432e47107 (diff)
downloadexternal_webkit-9364f22aed35e1a1e9d07c121510f80be3ab0502.zip
external_webkit-9364f22aed35e1a1e9d07c121510f80be3ab0502.tar.gz
external_webkit-9364f22aed35e1a1e9d07c121510f80be3ab0502.tar.bz2
Initial Contribution
Diffstat (limited to 'WebCore/plugins')
-rw-r--r--WebCore/plugins/PluginDatabase.cpp225
-rw-r--r--WebCore/plugins/PluginDatabase.h28
-rw-r--r--WebCore/plugins/PluginPackage.cpp119
-rw-r--r--WebCore/plugins/PluginPackage.h45
-rw-r--r--WebCore/plugins/PluginQuirkSet.h1
-rw-r--r--WebCore/plugins/PluginStream.cpp13
-rw-r--r--WebCore/plugins/PluginStream.h12
-rw-r--r--WebCore/plugins/PluginView.h19
-rw-r--r--WebCore/plugins/android/PlugInInfoStoreAndroid.cpp85
-rw-r--r--WebCore/plugins/android/PluginDatabaseAndroid.cpp347
-rw-r--r--WebCore/plugins/android/PluginDatabaseAndroid.h91
-rw-r--r--WebCore/plugins/android/PluginDebug.h44
-rw-r--r--WebCore/plugins/android/PluginPackageAndroid.cpp504
-rw-r--r--WebCore/plugins/android/PluginPackageAndroid.h152
-rw-r--r--WebCore/plugins/android/PluginViewAndroid.cpp567
-rw-r--r--WebCore/plugins/android/PluginViewAndroid.h176
-rw-r--r--WebCore/plugins/android/npapi.cpp200
-rw-r--r--WebCore/plugins/android/npfunctions.h201
-rw-r--r--WebCore/plugins/win/PluginDatabaseWin.cpp190
-rw-r--r--WebCore/plugins/win/PluginPackageWin.cpp309
-rw-r--r--WebCore/plugins/win/PluginViewWin.cpp137
21 files changed, 2885 insertions, 580 deletions
diff --git a/WebCore/plugins/PluginDatabase.cpp b/WebCore/plugins/PluginDatabase.cpp
deleted file mode 100644
index dba5ef9..0000000
--- a/WebCore/plugins/PluginDatabase.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Collabora, Ltd. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
- */
-
-#include "config.h"
-#include "PluginDatabase.h"
-
-#include "Frame.h"
-#include "KURL.h"
-#include "PluginPackage.h"
-#include <stdlib.h>
-
-namespace WebCore {
-
-PluginDatabase* PluginDatabase::installedPlugins()
-{
- static PluginDatabase* plugins = 0;
-
- if (!plugins) {
- plugins = new PluginDatabase;
- plugins->setPluginPaths(PluginDatabase::defaultPluginPaths());
- plugins->refresh();
- }
-
- return plugins;
-}
-
-bool PluginDatabase::isMIMETypeRegistered(const String& mimeType)
-{
- if (mimeType.isNull())
- return false;
- if (m_registeredMIMETypes.contains(mimeType))
- return true;
- // No plugin was found, try refreshing the database and searching again
- return (refresh() && m_registeredMIMETypes.contains(mimeType));
-}
-
-void PluginDatabase::addExtraPluginPath(const String& path)
-{
- m_pluginPaths.append(path);
- refresh();
-}
-
-bool PluginDatabase::refresh()
-{
- PluginSet newPlugins;
-
- bool pluginSetChanged = false;
-
- // Create a new set of plugins
- newPlugins = getPluginsInPaths();
-
- if (!m_plugins.isEmpty()) {
- m_registeredMIMETypes.clear();
-
- PluginSet pluginsToUnload = m_plugins;
-
- PluginSet::const_iterator end = newPlugins.end();
- for (PluginSet::const_iterator it = newPlugins.begin(); it != end; ++it)
- pluginsToUnload.remove(*it);
-
- end = m_plugins.end();
- for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it)
- newPlugins.remove(*it);
-
- // Unload plugins
- end = pluginsToUnload.end();
- for (PluginSet::const_iterator it = pluginsToUnload.begin(); it != end; ++it)
- m_plugins.remove(*it);
-
- // Add new plugins
- end = newPlugins.end();
- for (PluginSet::const_iterator it = newPlugins.begin(); it != end; ++it)
- m_plugins.add(*it);
-
- pluginSetChanged = !pluginsToUnload.isEmpty() || !newPlugins.isEmpty();
- } else {
- m_plugins = newPlugins;
- PluginSet::const_iterator end = newPlugins.end();
- for (PluginSet::const_iterator it = newPlugins.begin(); it != end; ++it)
- m_plugins.add(*it);
-
- pluginSetChanged = !newPlugins.isEmpty();
- }
-
- // Register plug-in MIME types
- 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_end = (*it)->mimeToDescriptions().end();
- for (MIMEToDescriptionsMap::const_iterator map_it = (*it)->mimeToDescriptions().begin(); map_it != map_end; ++map_it) {
- m_registeredMIMETypes.add(map_it->first);
- }
- }
-
- return pluginSetChanged;
-}
-
-Vector<PluginPackage*> PluginDatabase::plugins() const
-{
- Vector<PluginPackage*> result;
-
- PluginSet::const_iterator end = m_plugins.end();
- for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it)
- result.append((*it).get());
-
- return result;
-}
-
-int PluginDatabase::preferredPluginCompare(const void* a, const void* b)
-{
- PluginPackage* pluginA = *static_cast<PluginPackage* const*>(a);
- PluginPackage* pluginB = *static_cast<PluginPackage* const*>(b);
-
- return pluginA->compare(*pluginB);
-}
-
-PluginPackage* PluginDatabase::pluginForMIMEType(const String& mimeType)
-{
- if (mimeType.isEmpty())
- return 0;
-
- String key = mimeType.lower();
- PluginSet::const_iterator end = m_plugins.end();
-
- Vector<PluginPackage*, 2> pluginChoices;
-
- for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) {
- if ((*it)->mimeToDescriptions().contains(key))
- pluginChoices.append((*it).get());
- }
-
- if (pluginChoices.isEmpty())
- return 0;
-
- qsort(pluginChoices.data(), pluginChoices.size(), sizeof(PluginPackage*), PluginDatabase::preferredPluginCompare);
-
- return pluginChoices[0];
-}
-
-String PluginDatabase::MIMETypeForExtension(const String& extension) const
-{
- if (extension.isEmpty())
- return String();
-
- PluginSet::const_iterator end = m_plugins.end();
- String mimeType;
- Vector<PluginPackage*, 2> pluginChoices;
- HashMap<PluginPackage*, String> mimeTypeForPlugin;
-
- for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) {
- MIMEToExtensionsMap::const_iterator mime_end = (*it)->mimeToExtensions().end();
-
- for (MIMEToExtensionsMap::const_iterator mime_it = (*it)->mimeToExtensions().begin(); mime_it != mime_end; ++mime_it) {
- 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();
- pluginChoices.append(plugin);
- mimeTypeForPlugin.add(plugin, mime_it->first);
- foundMapping = true;
- break;
- }
- }
- if (foundMapping)
- break;
- }
- }
-
- if (pluginChoices.isEmpty())
- return String();
-
- qsort(pluginChoices.data(), pluginChoices.size(), sizeof(PluginPackage*), PluginDatabase::preferredPluginCompare);
-
- return mimeTypeForPlugin.get(pluginChoices[0]);
-}
-
-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("/")) {
- int extensionPos = filename.reverseFind('.');
- if (extensionPos != -1) {
- String extension = filename.substring(extensionPos + 1);
-
- mimeType = MIMETypeForExtension(extension);
- plugin = pluginForMIMEType(mimeType);
- }
- }
- }
-
- // FIXME: if no plugin could be found, query Windows for the mime type
- // corresponding to the extension.
-
- return plugin;
-}
-
-}
diff --git a/WebCore/plugins/PluginDatabase.h b/WebCore/plugins/PluginDatabase.h
index f79b881..71181b0 100644
--- a/WebCore/plugins/PluginDatabase.h
+++ b/WebCore/plugins/PluginDatabase.h
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,40 +26,47 @@
#ifndef PluginDatabase_H
#define PluginDatabase_H
-#include "PlatformString.h"
-#include "PluginPackage.h"
-#include "StringHash.h"
+#ifdef ANDROID_PLUGINS
+
+#include "PluginDatabaseAndroid.h"
+
+namespace WebCore {
+ typedef PluginDatabaseAndroid PluginDatabase;
+}
+
+#else // !defined(ANDROID_PLUGINS)
#include <wtf/Vector.h>
#include <wtf/HashSet.h>
+#include "PlatformString.h"
+#include "PluginPackage.h"
+#include "StringHash.h"
+
namespace WebCore {
class Element;
class Frame;
class IntSize;
class KURL;
class PluginPackage;
+ class PluginView;
typedef HashSet<RefPtr<PluginPackage>, PluginPackageHash> PluginSet;
class PluginDatabase {
public:
static PluginDatabase* installedPlugins();
+ PluginView* createPluginView(Frame* parentFrame, const IntSize&, Element* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually);
bool refresh();
Vector<PluginPackage*> plugins() const;
bool isMIMETypeRegistered(const String& mimeType);
void addExtraPluginPath(const String&);
-
- static bool isPreferredPluginPath(const String& path);
- static int preferredPluginCompare(const void*, const void*);
-
- PluginPackage* findPlugin(const KURL&, String& mimeType);
-
private:
void setPluginPaths(const Vector<String>& paths) { m_pluginPaths = paths; }
PluginSet getPluginsInPaths() const;
+ PluginPackage* findPlugin(const KURL& url, String& mimeType);
PluginPackage* pluginForMIMEType(const String& mimeType);
String MIMETypeForExtension(const String& extension) const;
@@ -73,4 +79,6 @@ namespace WebCore {
} // namespace WebCore
+#endif // !defined(ANDROID_PLUGINS)
+
#endif
diff --git a/WebCore/plugins/PluginPackage.cpp b/WebCore/plugins/PluginPackage.cpp
deleted file mode 100644
index 76882c8..0000000
--- a/WebCore/plugins/PluginPackage.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Collabora, Ltd. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
- */
-
-#include "config.h"
-#include "PluginPackage.h"
-
-#include "MIMETypeRegistry.h"
-#include "PluginDebug.h"
-#include "Timer.h"
-#include "npruntime_impl.h"
-#include <wtf/OwnArrayPtr.h>
-
-namespace WebCore {
-
-PluginPackage::~PluginPackage()
-{
- ASSERT(!m_isLoaded);
-}
-
-void PluginPackage::freeLibrarySoon()
-{
- ASSERT(!m_freeLibraryTimer.isActive());
- ASSERT(m_module);
- ASSERT(m_loadCount == 0);
-
- m_freeLibraryTimer.startOneShot(0);
-}
-
-void PluginPackage::freeLibraryTimerFired(Timer<PluginPackage>*)
-{
- ASSERT(m_module);
- ASSERT(m_loadCount == 0);
-
- unloadModule(m_module);
- m_module = 0;
-}
-
-PluginPackage::PluginPackage(const String& path, const PlatformFileTime& lastModified)
- : RefCounted<PluginPackage>(0)
- , m_path(path)
- , m_moduleVersion(0)
- , m_module(0)
- , m_lastModified(lastModified)
- , m_isLoaded(false)
- , m_loadCount(0)
- , m_freeLibraryTimer(this, &PluginPackage::freeLibraryTimerFired)
-{
- m_fileName = pathGetFileName(m_path);
- m_parentDirectory = m_path.left(m_path.length() - m_fileName.length() - 1);
-}
-
-void PluginPackage::unload()
-{
- if (!m_isLoaded)
- return;
-
- if (--m_loadCount > 0)
- return;
-
- m_NPP_Shutdown();
-
- unloadWithoutShutdown();
-}
-
-void PluginPackage::unloadWithoutShutdown()
-{
- if (!m_isLoaded)
- return;
-
- ASSERT(m_loadCount == 0);
- ASSERT(m_module);
-
- // <rdar://5530519>: Crash when closing tab with pdf file (Reader 7 only)
- // If the plugin has subclassed its parent window, as with Reader 7, we may have
- // gotten here by way of the plugin's internal window proc forwarding a message to our
- // original window proc. If we free the plugin library from here, we will jump back
- // to code we just freed when we return, so delay calling FreeLibrary at least until
- // the next message loop
- freeLibrarySoon();
-
- m_isLoaded = false;
-}
-
-PluginPackage* PluginPackage::createPackage(const String& path, const PlatformFileTime& lastModified)
-{
- PluginPackage* package = new PluginPackage(path, lastModified);
-
- if (!package->fetchInfo()) {
- delete package;
- return 0;
- }
-
- return package;
-}
-
-}
diff --git a/WebCore/plugins/PluginPackage.h b/WebCore/plugins/PluginPackage.h
index 7a46983..ab15e33 100644
--- a/WebCore/plugins/PluginPackage.h
+++ b/WebCore/plugins/PluginPackage.h
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,11 +26,22 @@
#ifndef PluginPackage_H
#define PluginPackage_H
-#include "FileSystem.h"
-#include "PlatformString.h"
-#include "PluginQuirkSet.h"
-#include "StringHash.h"
+#ifdef ANDROID_PLUGINS
+
+#include "PluginPackageAndroid.h"
+
+namespace WebCore {
+ typedef PluginPackageAndroid PluginPackage;
+}
+
+#else !defined(ANDROID_PLUGINS)
+
+#include <winsock2.h>
+#include <windows.h>
+
#include "Timer.h"
+#include "StringHash.h"
+#include "PlatformString.h"
#include "npfunctions.h"
#include <wtf/HashMap.h>
#include <wtf/RefCounted.h>
@@ -43,7 +53,7 @@ namespace WebCore {
class PluginPackage : public RefCounted<PluginPackage> {
public:
~PluginPackage();
- static PluginPackage* createPackage(const String& path, const PlatformFileTime& lastModified);
+ static PluginPackage* createPackage(const String& path, const FILETIME& lastModified);
String name() const { return m_name; }
String description() const { return m_description; }
@@ -53,7 +63,7 @@ namespace WebCore {
const MIMEToDescriptionsMap& mimeToDescriptions() const { return m_mimeToDescriptions; }
const MIMEToExtensionsMap& mimeToExtensions() const { return m_mimeToExtensions; }
- unsigned hash() const;
+ unsigned PluginPackage::hash() const;
static bool equal(const PluginPackage& a, const PluginPackage& b);
bool load();
@@ -61,33 +71,31 @@ namespace WebCore {
void unloadWithoutShutdown();
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; }
+ int compareFileVersion(unsigned compareVersionMS, unsigned compareVersionLS) const;
private:
- PluginPackage(const String& path, const PlatformFileTime& lastModified);
+ PluginPackage(const String& path, const FILETIME& lastModified);
bool fetchInfo();
+ void storeFileVersion(LPVOID versionInfoData);
bool isPluginBlacklisted();
- void determineQuirks(const String& mimeType);
bool m_isLoaded;
int m_loadCount;
+ DWORD m_fileVersionMS;
+ DWORD m_fileVersionLS;
+
String m_description;
String m_path;
String m_fileName;
String m_name;
String m_parentDirectory;
- PlatformModuleVersion m_moduleVersion;
-
MIMEToDescriptionsMap m_mimeToDescriptions;
MIMEToExtensionsMap m_mimeToExtensions;
- PlatformModule m_module;
- PlatformFileTime m_lastModified;
+ HMODULE m_module;
+ FILETIME m_lastModified;
NPP_ShutdownProcPtr m_NPP_Shutdown;
NPPluginFuncs m_pluginFuncs;
@@ -96,8 +104,6 @@ namespace WebCore {
void freeLibrarySoon();
void freeLibraryTimerFired(Timer<PluginPackage>*);
Timer<PluginPackage> m_freeLibraryTimer;
-
- PluginQuirkSet m_quirks;
};
struct PluginPackageHash {
@@ -121,5 +127,6 @@ namespace WTF {
};
}
+#endif // !defined(ANDROID_PLUGINS)
#endif
diff --git a/WebCore/plugins/PluginQuirkSet.h b/WebCore/plugins/PluginQuirkSet.h
index e93f6e0..031baa0 100644
--- a/WebCore/plugins/PluginQuirkSet.h
+++ b/WebCore/plugins/PluginQuirkSet.h
@@ -44,7 +44,6 @@ namespace WebCore {
PluginQuirkFlashURLNotifyBug = 1 << 8,
PluginQuirkDontClipToZeroRectWhenScrolling = 1 << 9,
PluginQuirkDontSetNullWindowHandleOnDestroy = 1 << 10,
- PluginQuirkDontAllowMultipleInstances = 1 << 11,
};
class PluginQuirkSet {
diff --git a/WebCore/plugins/PluginStream.cpp b/WebCore/plugins/PluginStream.cpp
index 0e6a445..a206b51 100644
--- a/WebCore/plugins/PluginStream.cpp
+++ b/WebCore/plugins/PluginStream.cpp
@@ -52,8 +52,7 @@ static StreamMap& streams()
}
PluginStream::PluginStream(PluginStreamClient* client, Frame* frame, const ResourceRequest& resourceRequest, bool sendNotification, void* notifyData, const NPPluginFuncs* pluginFuncs, NPP instance, const PluginQuirkSet& quirks)
- : RefCounted<PluginStream>(0)
- , m_resourceRequest(resourceRequest)
+ : m_resourceRequest(resourceRequest)
, m_client(client)
, m_frame(frame)
, m_notifyData(notifyData)
@@ -130,10 +129,14 @@ void PluginStream::startStream()
// Some plugins (Flash) expect that javascript URLs are passed back decoded as this is the
// format used when requesting the URL.
+#ifdef ANDROID_JAVASCRIPT_SECURITY
if (responseURL.protocolIs("javascript"))
- m_stream.url = strdup(decodeURLEscapeSequences(responseURL.string()).utf8().data());
+#else
+ if (responseURL.string().startsWith("javascript:", false))
+#endif
+ m_stream.url = strdup(responseURL.decode_string(responseURL.deprecatedString()).utf8());
else
- m_stream.url = strdup(responseURL.string().utf8().data());
+ m_stream.url = strdup(responseURL.deprecatedString().utf8());
CString mimeTypeStr = m_resourceResponse.mimeType().utf8();
@@ -284,7 +287,7 @@ void PluginStream::destroyStream()
// destructor, so reset it to 0
m_stream.url = 0;
}
- m_pluginFuncs->urlnotify(m_instance, m_resourceRequest.url().string().utf8().data(), m_reason, m_notifyData);
+ m_pluginFuncs->urlnotify(m_instance, m_resourceRequest.url().deprecatedString().utf8(), m_reason, m_notifyData);
if (m_loader)
m_loader->setDefersLoading(false);
}
diff --git a/WebCore/plugins/PluginStream.h b/WebCore/plugins/PluginStream.h
index 921a50d..6eb7b81 100644
--- a/WebCore/plugins/PluginStream.h
+++ b/WebCore/plugins/PluginStream.h
@@ -27,6 +27,16 @@
#ifndef PluginStream_H
#define PluginStream_H
+#ifdef ANDROID_PLUGINS
+
+#include "PluginStreamAndroid.h"
+
+namespace WebCore {
+ typedef PluginStreamAndroid PluginStream;
+}
+
+#else // !defined(ANDROID_PLUGINS)
+
#include "CString.h"
#include "FileSystem.h"
#include "KURL.h"
@@ -113,4 +123,6 @@ namespace WebCore {
} // namespace WebCore
+#endif // !defined(ANDROID_PLUGINS)
+
#endif
diff --git a/WebCore/plugins/PluginView.h b/WebCore/plugins/PluginView.h
index 3e4fc10..9256256 100644
--- a/WebCore/plugins/PluginView.h
+++ b/WebCore/plugins/PluginView.h
@@ -27,6 +27,16 @@
#ifndef PluginView_H
#define PluginView_H
+#ifdef ANDROID_PLUGINS
+
+#include "PluginViewAndroid.h"
+
+namespace WebCore {
+ typedef PluginViewAndroid PluginView;
+}
+
+#else // !defined(ANDROID_PLUGINS)
+
#include <winsock2.h>
#include <windows.h>
@@ -35,6 +45,7 @@
#include "KURL.h"
#include "PlatformString.h"
#include "PluginStream.h"
+#include "PluginQuirkSet.h"
#include "ResourceRequest.h"
#include "Timer.h"
#include "Widget.h"
@@ -75,7 +86,7 @@ namespace WebCore {
friend static LRESULT CALLBACK PluginViewWndProc(HWND, UINT, WPARAM, LPARAM);
public:
- static PluginView* create(Frame* parentFrame, const IntSize&, Element*, const KURL&, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually);
+ PluginView(Frame* parentFrame, const IntSize&, PluginPackage* plugin, Element*, const KURL&, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually);
virtual ~PluginView();
PluginPackage* plugin() const { return m_plugin.get(); }
@@ -137,8 +148,6 @@ namespace WebCore {
static bool isCallingPlugin();
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);
void init();
bool start();
@@ -170,6 +179,7 @@ namespace WebCore {
OwnPtr<PluginMessageThrottlerWin> m_messageThrottler;
void updateWindow() const;
+ void determineQuirks(const String& mimeType);
void paintMissingPluginIcon(GraphicsContext*, const IntRect&);
void handleKeyboardEvent(KeyboardEvent*);
@@ -192,6 +202,7 @@ namespace WebCore {
HashSet<RefPtr<PluginStream> > m_streams;
Vector<PluginRequest*> m_requests;
+ PluginQuirkSet m_quirks;
bool m_isWindowed;
bool m_isTransparent;
bool m_isVisible;
@@ -214,4 +225,6 @@ namespace WebCore {
} // namespace WebCore
+#endif // !defined(ANDROID_PLUGINS)
+
#endif
diff --git a/WebCore/plugins/android/PlugInInfoStoreAndroid.cpp b/WebCore/plugins/android/PlugInInfoStoreAndroid.cpp
new file mode 100644
index 0000000..780e5f0
--- /dev/null
+++ b/WebCore/plugins/android/PlugInInfoStoreAndroid.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
+ */
+
+#include "config.h"
+#include "PluginInfoStore.h"
+#include "PluginDatabaseAndroid.h"
+#include "PluginPackageAndroid.h"
+
+namespace WebCore {
+
+PluginInfo* PluginInfoStore::createPluginInfoForPluginAtIndex(unsigned i)
+{
+ PluginDatabaseAndroid *db = PluginDatabaseAndroid::installedPlugins();
+ PluginInfo* info = new PluginInfo;
+ PluginPackageAndroid* package = db->plugins()[i];
+
+ info->name = package->name();
+ info->file = package->fileName();
+ info->desc = package->description();
+
+ const MIMEToDescriptionsMap& mimeToDescriptions = package->mimeToDescriptions();
+ MIMEToDescriptionsMap::const_iterator end = mimeToDescriptions.end();
+ for (MIMEToDescriptionsMap::const_iterator it = mimeToDescriptions.begin(); it != end; ++it) {
+ MimeClassInfo* mime = new MimeClassInfo;
+ info->mimes.append(mime);
+
+ mime->type = it->first;
+ mime->desc = it->second;
+ mime->plugin = info;
+
+ Vector<String> extensions = package->mimeToExtensions().get(mime->type);
+
+ for (unsigned i = 0; i < extensions.size(); i++) {
+ if (i > 0)
+ mime->suffixes += ",";
+
+ mime->suffixes += extensions[i];
+ }
+ }
+
+ return info;
+}
+
+unsigned PluginInfoStore::pluginCount() const
+{
+ return PluginDatabaseAndroid::installedPlugins()->plugins().size();
+}
+
+bool PluginInfoStore::supportsMIMEType(const WebCore::String& mimeType)
+{
+ return PluginDatabaseAndroid::installedPlugins()->isMIMETypeRegistered(mimeType);
+}
+
+void refreshPlugins(bool reloadOpenPages)
+{
+ PluginDatabaseAndroid::installedPlugins()->refresh();
+
+ if (reloadOpenPages) {
+ // FIXME: reload open pages
+ }
+}
+
+}
diff --git a/WebCore/plugins/android/PluginDatabaseAndroid.cpp b/WebCore/plugins/android/PluginDatabaseAndroid.cpp
new file mode 100644
index 0000000..411855c
--- /dev/null
+++ b/WebCore/plugins/android/PluginDatabaseAndroid.cpp
@@ -0,0 +1,347 @@
+#ifdef ANDROID_PLUGINS
+
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
+ */
+
+#include "config.h"
+#include "PluginDatabaseAndroid.h"
+#include "PluginPackageAndroid.h"
+#include "PluginViewAndroid.h"
+#include "Frame.h"
+#include <sys/types.h>
+#include <dirent.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include "PluginDebug.h"
+
+namespace WebCore {
+
+String PluginDatabaseAndroid::s_defaultPluginsPath;
+
+PluginDatabaseAndroid* PluginDatabaseAndroid::installedPlugins()
+{
+ static PluginDatabaseAndroid* plugins = 0;
+
+ if (!plugins) {
+ plugins = new PluginDatabaseAndroid;
+ plugins->refresh();
+ }
+
+ return plugins;
+}
+
+void PluginDatabaseAndroid::setDefaultPluginsPath(const String& path)
+{
+ // Change the default plugins path and rescan.
+ if(path != s_defaultPluginsPath) {
+ s_defaultPluginsPath = path;
+ installedPlugins()->refresh();
+ }
+}
+
+PluginDatabaseAndroid::PluginDatabaseAndroid()
+ : m_pluginsPaths()
+ , m_plugins()
+{
+}
+
+PluginDatabaseAndroid::~PluginDatabaseAndroid()
+{
+}
+
+void PluginDatabaseAndroid::addExtraPluginPath(const String& path)
+{
+ m_pluginsPaths.append(path);
+ refresh();
+}
+
+bool PluginDatabaseAndroid::addPluginFile(const String& path)
+{
+ PLUGIN_LOG("Adding plugin \"%s\"\n", path.utf8().data());
+
+ // Check if the plugin is already loaded.
+ PluginPackageAndroid* plugin = findPluginByPath(path);
+
+ // Stat the file to check we can access it.
+ struct stat statbuf;
+ if(stat(path.utf8().data(), &statbuf)) {
+ // Stat failed. We can't access this file.
+ PLUGIN_LOG("Couldn't stat library \"%s\": %s\n",
+ path.utf8().data(), strerror(errno));
+ // Well, can't load this plugin, then.
+ if(plugin) {
+ // If we previous succeeded loading it, unload it now.
+ removePlugin(plugin);
+ }
+ // Failed to load.
+ return false;
+ }
+
+ // Check the modification time.
+ uint32 lastModified = statbuf.st_mtime;
+ if(plugin) {
+ // Compare to the currently loaded version.
+ if(lastModified == plugin->getLastModified()) {
+ // It's the same plugin. No new actions required.
+ return true;
+ } else {
+ // It has been modified. Unload the old version.
+ removePlugin(plugin);
+ }
+ }
+
+ // If we get here, we either just unloaded an old plugin, or this
+ // is a new one. Create a new package.
+ PluginPackageAndroid* package =
+ PluginPackageAndroid::createPackage(path, lastModified);
+ if(package) {
+ // Success, add to the vector of plugins.
+ PLUGIN_LOG("Successfully added plugin \"%s\"\n", path.utf8().data());
+ m_plugins.append(package);
+ return true;
+ } else {
+ // Failed.
+ return false;
+ }
+}
+
+bool PluginDatabaseAndroid::addPluginsInDirectory(const String& path)
+{
+ // Open a directory iterator
+ DIR* dir_it = opendir(path.utf8().data());
+ if(!dir_it) {
+ PLUGIN_LOG("Cannot open directory \"%s\"\n",
+ path.utf8().data());
+ return false;
+ }
+ // Scan the directory for "*.so" and "*.so.*" files.
+ struct dirent* entry;
+ while((entry = readdir(dir_it)) != NULL) {
+ const char* name = entry->d_name;
+ // Skip current and parent directory entries.
+ if(!strcmp(name, ".") || !strcmp(name, ".."))
+ continue;
+ const char* so = strstr(name, ".so");
+ if(so && (so[3] == 0 || so[3] == '.')) {
+ // Matches our pattern, add it.
+ addPluginFile(path + "/" + name);
+ }
+ }
+ closedir(dir_it);
+ return true;
+}
+
+void PluginDatabaseAndroid::removePlugin(PluginPackageAndroid* plugin)
+{
+ // Find this plugin in the array and remove it.
+ for(unsigned i = 0; i < m_plugins.size(); ++i) {
+ if(m_plugins[i] == plugin) {
+ PLUGIN_LOG("Removed plugin \"%s\"\n",
+ plugin->path().utf8().data());
+ // This will cause a reference count to decrement. When
+ // the plugin actually stops getting used by all
+ // documents, its instance will delete itself.
+ m_plugins.remove(i);
+ break;
+ }
+ }
+ PLUGIN_LOG("Tried to remove plugin %p which didn't exist!\n", plugin);
+}
+
+bool PluginDatabaseAndroid::refresh()
+{
+ PLUGIN_LOG("PluginDatabaseAndroid::refresh()\n");
+
+ // Don't delete existing plugins. The directory scan will add new
+ // plugins and also refresh old plugins if their file is modified
+ // since the last check.
+
+ // Scan each directory and add any plugins found in them. This is
+ // not recursive.
+ if(s_defaultPluginsPath.length() > 0)
+ addPluginsInDirectory(s_defaultPluginsPath);
+ for(unsigned i = 0; i < m_pluginsPaths.size(); ++i)
+ addPluginsInDirectory(m_pluginsPaths[i]);
+
+ // Now stat() all plugins and remove any that we can't
+ // access. This handles the case of a plugin being deleted at
+ // runtime.
+ for(unsigned i = 0; i < m_plugins.size();) {
+ struct stat statbuf;
+ if(stat(m_plugins[i]->path().utf8().data(), &statbuf)) {
+ // It's gone away. Remove it from the list.
+ m_plugins.remove(i);
+ } else {
+ ++i;
+ }
+ }
+
+ return true;
+}
+
+Vector<PluginPackageAndroid*> PluginDatabaseAndroid::plugins() const
+{
+ Vector<PluginPackageAndroid*> result;
+
+ for(PackageRefVector::const_iterator it = m_plugins.begin();
+ it != m_plugins.end(); ++it)
+ result.append(it->get());
+
+ return result;
+}
+
+bool PluginDatabaseAndroid::isMIMETypeRegistered(const String& mimeType) const
+{
+ // Iterate through every package
+ for(PackageRefVector::const_iterator it = m_plugins.begin();
+ it != m_plugins.end(); ++it) {
+ // Check if this package has the MIME type mapped to an extension
+ const PluginPackageAndroid *package = it->get();
+ const MIMEToExtensionsMap& mime_extension_map =
+ package->mimeToExtensions();
+ if(mime_extension_map.find(mimeType) != mime_extension_map.end()) {
+ // Found it
+ return true;
+ }
+ }
+ // No package has this MIME type
+ return false;
+}
+
+bool PluginDatabaseAndroid::isPluginBlacklisted(PluginPackageAndroid* plugin)
+{
+ // If there is ever a plugin in the wild which causes the latest
+ // version of Android to crash, then stick a check here for it and
+ // return true when matched.
+ return false;
+}
+
+PluginPackageAndroid* PluginDatabaseAndroid::pluginForMIMEType(
+ const String& mimeType)
+{
+ // Todo: these data structures are not right. This is inefficient.
+ // Iterate through every package
+ for(PackageRefVector::iterator it = m_plugins.begin();
+ it != m_plugins.end(); ++it) {
+ // Check if this package has the MIME type mapped to a description
+ PluginPackageAndroid *package = it->get();
+ const MIMEToDescriptionsMap& mime_desc_map =
+ package->mimeToDescriptions();
+ if(mime_desc_map.find(mimeType) != mime_desc_map.end()) {
+ // Found it
+ return package;
+ }
+ }
+ // No package has this MIME type
+ return NULL;
+}
+
+String PluginDatabaseAndroid::MIMETypeForExtension(const String& extension)
+ const
+{
+ // Todo: these data structures are not right. This is inefficient.
+ // Iterate through every package
+ for(PackageRefVector::const_iterator it = m_plugins.begin();
+ it != m_plugins.end(); ++it) {
+ // Check if this package has the MIME type mapped to an extension
+ PluginPackageAndroid *package = it->get();
+ const MIMEToDescriptionsMap& mime_desc_map =
+ package->mimeToDescriptions();
+ for(MIMEToDescriptionsMap::const_iterator map_it =
+ mime_desc_map.begin();
+ map_it != mime_desc_map.end(); ++map_it) {
+ if(map_it->second == extension) {
+ // Found it
+ return map_it->first;
+ }
+ }
+ }
+ // No MIME type matches this extension
+ return String("");
+}
+
+PluginPackageAndroid* PluginDatabaseAndroid::findPlugin(const KURL& url,
+ String& mimeType)
+{
+ PluginPackageAndroid* plugin = pluginForMIMEType(mimeType);
+ String filename = url.string();
+
+ if (!plugin) {
+ String filename = url.lastPathComponent();
+ if (!filename.endsWith("/")) {
+ int extensionPos = filename.reverseFind('.');
+ if (extensionPos != -1) {
+ String extension = filename.substring(extensionPos + 1);
+
+ mimeType = MIMETypeForExtension(extension);
+ if (mimeType.length()) {
+ plugin = pluginForMIMEType(mimeType);
+ }
+ }
+ }
+ }
+ // No MIME type matches this url
+ return plugin;
+}
+
+PluginPackageAndroid* PluginDatabaseAndroid::findPluginByPath(
+ const String& path)
+{
+ for(PackageRefVector::iterator it = m_plugins.begin();
+ it != m_plugins.end(); ++it) {
+ if((*it)->path() == path)
+ return it->get(); // Found it
+ }
+ return 0; // Not found.
+}
+
+PluginViewAndroid* PluginDatabaseAndroid::createPluginView(
+ Frame* parentFrame,
+ const IntSize& size,
+ Element* element,
+ const KURL& url,
+ const Vector<String>& paramNames,
+ const Vector<String>& paramValues,
+ const String& mimeType,
+ bool loadManually)
+{
+ // if we fail to find a plugin for this MIME type, findPlugin will search for
+ // a plugin by the file extension and update the MIME type, so pass a mutable String
+ String mimeTypeCopy = mimeType;
+ PluginPackageAndroid* plugin = findPlugin(url, mimeTypeCopy);
+
+ // No plugin was found, try refreshing the database and searching again
+ if (!plugin && refresh()) {
+ mimeTypeCopy = mimeType;
+ plugin = findPlugin(url, mimeTypeCopy);
+ }
+
+ return new PluginViewAndroid(parentFrame, size, plugin, element, url, paramNames, paramValues, mimeTypeCopy, loadManually);
+}
+
+}
+
+#endif
diff --git a/WebCore/plugins/android/PluginDatabaseAndroid.h b/WebCore/plugins/android/PluginDatabaseAndroid.h
new file mode 100644
index 0000000..72814e9
--- /dev/null
+++ b/WebCore/plugins/android/PluginDatabaseAndroid.h
@@ -0,0 +1,91 @@
+#ifdef ANDROID_PLUGINS
+
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 PluginDatabaseAndroid_H
+#define PluginDatabaseAndroid_H
+
+#include <wtf/Vector.h>
+
+#include "PlatformString.h"
+#include "PluginPackageAndroid.h"
+
+namespace WebCore {
+ class Element;
+ class Frame;
+ class IntSize;
+ class KURL;
+ class PluginPackageAndroid;
+ class PluginViewAndroid;
+
+ class PluginDatabaseAndroid {
+ public:
+ ~PluginDatabaseAndroid();
+
+ static PluginDatabaseAndroid* installedPlugins();
+ PluginViewAndroid* createPluginView(Frame* parentFrame,
+ const IntSize&,
+ Element* element,
+ const KURL& url,
+ const Vector<String>& paramNames,
+ const Vector<String>& paramValues,
+ const String& mimeType,
+ bool loadManually);
+
+ bool refresh();
+ Vector<PluginPackageAndroid*> plugins() const;
+ bool isMIMETypeRegistered(const String& mimeType) const;
+ void addExtraPluginPath(const String&);
+ static bool isPluginBlacklisted(PluginPackageAndroid* plugin);
+ static void setDefaultPluginsPath(const String&);
+
+ private:
+ explicit PluginDatabaseAndroid();
+
+ bool addPluginFile(const String& path);
+ bool addPluginsInDirectory(const String& path);
+ PluginPackageAndroid* findPlugin(const KURL& url, String& mimeType);
+ PluginPackageAndroid* pluginForMIMEType(const String& mimeType);
+ String MIMETypeForExtension(const String& extension) const;
+ PluginPackageAndroid* findPluginByPath(const String& path);
+ void removePlugin(PluginPackageAndroid* plugin);
+
+ // List of all paths to search for plugins
+ Vector<String> m_pluginsPaths;
+
+ // List of all PluginPackageAndroid instances
+ typedef Vector<RefPtr<PluginPackageAndroid> > PackageRefVector;
+ PackageRefVector m_plugins;
+
+ // The default plugins path from Settings.
+ static String s_defaultPluginsPath;
+ };
+
+} // namespace WebCore
+
+#endif
+
+#endif
diff --git a/WebCore/plugins/android/PluginDebug.h b/WebCore/plugins/android/PluginDebug.h
new file mode 100644
index 0000000..8adbbd7
--- /dev/null
+++ b/WebCore/plugins/android/PluginDebug.h
@@ -0,0 +1,44 @@
+#ifdef ANDROID_PLUGINS
+
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef PLUGIN_DEBUG_H__
+#define PLUGIN_DEBUG_H__
+
+// Include this file last to avoid clashes with the definition of LOG.
+
+#undef LOG
+#define LOG_TAG "WebKit"
+#include "utils/Log.h"
+
+// Define PLUGIN_DEBUG_LOCAL in an individual C++ file to enable for
+// that file only.
+
+// Define PLUGIN_DEBUG_GLOBAL to 1 to turn plug-in debug for all
+// Android plug-in code in this direectory.
+#define PLUGIN_DEBUG_GLOBAL 0
+
+#if PLUGIN_DEBUG_GLOBAL || defined(PLUGIN_DEBUG_LOCAL)
+# define PLUGIN_LOG(A, B...) do { LOGI( A , ## B ); } while(0)
+#else
+# define PLUGIN_LOG(A, B...) do { } while(0)
+#endif
+
+#endif // defined(PLUGIN_DEBUG_H__)
+
+#endif // defined(ANDROID_PLUGINS)
diff --git a/WebCore/plugins/android/PluginPackageAndroid.cpp b/WebCore/plugins/android/PluginPackageAndroid.cpp
new file mode 100644
index 0000000..b8dca9a
--- /dev/null
+++ b/WebCore/plugins/android/PluginPackageAndroid.cpp
@@ -0,0 +1,504 @@
+#ifdef ANDROID_PLUGINS
+
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
+ */
+
+#include "config.h"
+#include "WebCoreJni.h"
+#include "PluginPackageAndroid.h"
+#include "PluginDatabaseAndroid.h"
+
+#include "Timer.h"
+#include "DeprecatedString.h"
+#include "PlatformString.h"
+#include "CString.h"
+#include "npruntime_impl.h"
+
+#include <dlfcn.h>
+#include <errno.h>
+
+#include "PluginDebug.h"
+
+namespace WebCore {
+
+PluginPackageAndroid::PluginPackageAndroid(const String& path,
+ uint32 lastModified)
+ : m_path(path),
+ m_name(),
+ m_fileName(),
+ m_description(),
+ m_lastModified(lastModified),
+ m_pluginFuncs(),
+ m_mimeToDescriptions(),
+ m_mimeToExtensions(),
+ m_env(0),
+ m_pluginObject(0),
+ m_libraryHandle(NULL),
+ m_libraryInitialized(false),
+ m_NP_Initialize((NP_InitializeFuncPtr) NULL),
+ m_NP_Shutdown((NP_ShutdownFuncPtr) NULL),
+ m_NP_GetMIMEDescription((NP_GetMIMEDescriptionFuncPtr) NULL),
+ m_NP_GetValue((NP_GetValueFuncPtr) NULL)
+{
+ PLUGIN_LOG("Constructing PluginPackageAndroid\n");
+ if(android::WebCoreJni::getJavaVM()->GetEnv((void**) &m_env,
+ JNI_VERSION_1_4) != JNI_OK) {
+ PLUGIN_LOG("GetEnv failed!");
+ }
+}
+
+PluginPackageAndroid::~PluginPackageAndroid()
+{
+ PLUGIN_LOG("Destructing PluginPackageAndroid\n");
+ unload();
+}
+
+void PluginPackageAndroid::initializeBrowserFuncs()
+{
+ // Initialize the NPN function pointers that we hand over to the
+ // plugin.
+
+ memset(&m_browserFuncs, 0, sizeof(m_browserFuncs));
+
+ 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.pluginthreadasynccall = NPN_PluginThreadAsyncCall;
+
+ 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.intfromidentifier = _NPN_IntFromIdentifier;
+ 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_HasProperty;
+ m_browserFuncs.hasmethod = _NPN_HasMethod;
+ m_browserFuncs.setexception = _NPN_SetException;
+ m_browserFuncs.enumerate = _NPN_Enumerate;
+}
+
+jobject PluginPackageAndroid::createPluginObject(const char *name,
+ const char *path,
+ const char *fileName,
+ const char *description)
+{
+ // Create a Java "class Plugin" object instance
+ jclass pluginClass = m_env->FindClass("android/webkit/Plugin");
+ if(!pluginClass) {
+ PLUGIN_LOG("Couldn't find class android.webkit.Plugin\n");
+ return 0;
+ }
+ // Get Plugin(String, String, String, String, Context)
+ jmethodID pluginConstructor = m_env->GetMethodID(
+ pluginClass,
+ "<init>",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
+ if(!pluginConstructor) {
+ PLUGIN_LOG("Couldn't get android.webkit.Plugin constructor\n");
+ return 0;
+ }
+ // Make Java strings of name, path, fileName, description
+ jstring javaName = m_env->NewStringUTF(name);
+ jstring javaPath = m_env->NewStringUTF(m_path.utf8().data());
+ jstring javaFileName = m_env->NewStringUTF(m_fileName.utf8().data());
+ jstring javaDescription = m_env->NewStringUTF(description);
+ // Make a plugin instance
+ jobject pluginObject = m_env->NewObject(pluginClass,
+ pluginConstructor,
+ javaName,
+ javaPath,
+ javaFileName,
+ javaDescription);
+ return pluginObject;
+}
+
+jobject PluginPackageAndroid::getPluginListObject()
+{
+ // Get WebView.getPluginList()
+ jclass webViewClass = m_env->FindClass("android/webkit/WebView");
+ if(!webViewClass) {
+ PLUGIN_LOG("Couldn't find class android.webkit.WebView\n");
+ return 0;
+ }
+ jmethodID getPluginList = m_env->GetStaticMethodID(
+ webViewClass,
+ "getPluginList",
+ "()Landroid/webkit/PluginList;");
+ if(!getPluginList) {
+ PLUGIN_LOG("Couldn't find android.webkit.WebView.getPluginList()\n");
+ return 0;
+ }
+ // Get the PluginList instance
+ jobject pluginListObject = m_env->CallStaticObjectMethod(webViewClass,
+ getPluginList);
+ if(!pluginListObject) {
+ PLUGIN_LOG("Couldn't get PluginList object\n");
+ return 0;
+ }
+ return pluginListObject;
+}
+
+bool PluginPackageAndroid::addPluginObjectToList(jobject pluginList,
+ jobject plugin)
+{
+ // Add the Plugin object
+ jclass pluginListClass = m_env->FindClass("android/webkit/PluginList");
+ if(!pluginListClass) {
+ PLUGIN_LOG("Couldn't find class android.webkit.PluginList\n");
+ return false;
+ }
+ jmethodID addPlugin = m_env->GetMethodID(
+ pluginListClass,
+ "addPlugin",
+ "(Landroid/webkit/Plugin;)V");
+ if(!addPlugin) {
+ PLUGIN_LOG("Couldn't find android.webkit.PluginList.addPlugin()\n");
+ return false;
+ }
+ m_env->CallVoidMethod(pluginList,
+ addPlugin,
+ plugin);
+ return true;
+}
+
+void PluginPackageAndroid::removePluginObjectFromList(jobject pluginList,
+ jobject plugin)
+{
+ // Remove the Plugin object
+ jclass pluginListClass = m_env->FindClass("android/webkit/PluginList");
+ if(!pluginListClass) {
+ PLUGIN_LOG("Couldn't find class android.webkit.PluginList\n");
+ return;
+ }
+ jmethodID removePlugin = m_env->GetMethodID(
+ pluginListClass,
+ "removePlugin",
+ "(Landroid/webkit/Plugin;)V");
+ if(!removePlugin) {
+ PLUGIN_LOG("Couldn't find android.webkit.PluginList.removePlugin()\n");
+ return;
+ }
+ m_env->CallVoidMethod(pluginList,
+ removePlugin,
+ plugin);
+}
+
+bool PluginPackageAndroid::load()
+{
+ if(m_libraryHandle) {
+ PLUGIN_LOG("Plugin \"%s\" already loaded\n", m_path.utf8().data());
+ return true;
+ }
+
+ PLUGIN_LOG("Loading \"%s\"\n", m_path.utf8().data());
+
+ // Open the library
+ void *handle = dlopen(m_path.utf8().data(), RTLD_NOW);
+ if(!handle) {
+ PLUGIN_LOG("Couldn't load plugin library \"%s\": %s\n",
+ m_path.utf8().data(), dlerror());
+ return false;
+ }
+ m_libraryHandle = handle;
+ // This object will call dlclose() and set m_libraryHandle to NULL
+ // when going out of scope.
+ DynamicLibraryCloser dlCloser(this);
+
+ // Get the four entry points we need for Linux Netscape Plug-ins
+ if(!getEntryPoint("NP_Initialize", (void **) &m_NP_Initialize) ||
+ !getEntryPoint("NP_Shutdown", (void **) &m_NP_Shutdown) ||
+ !getEntryPoint("NP_GetMIMEDescription",
+ (void **) &m_NP_GetMIMEDescription) ||
+ !getEntryPoint("NP_GetValue", (void **) &m_NP_GetValue)) {
+ // If any of those failed to resolve, fail the entire load
+ return false;
+ }
+
+ // Get the plugin name and description using NP_GetValue
+ const char *name;
+ const char *description;
+ if(m_NP_GetValue(NULL, NPPVpluginNameString,
+ &name) != NPERR_NO_ERROR ||
+ m_NP_GetValue(NULL, NPPVpluginDescriptionString,
+ &description) != NPERR_NO_ERROR) {
+ PLUGIN_LOG("Couldn't get name/description using NP_GetValue\n");
+ return false;
+ }
+
+ PLUGIN_LOG("Plugin name: \"%s\"\n", name);
+ PLUGIN_LOG("Plugin description: \"%s\"\n", description);
+ m_name = name;
+ m_description = description;
+
+ // fileName is just the trailing part of the path
+ int last_slash = m_path.reverseFind('/');
+ if(last_slash < 0)
+ m_fileName = m_path;
+ else
+ m_fileName = m_path.substring(last_slash + 1);
+
+ // Grab the MIME description. This is in the format, e.g:
+ // application/x-somescriptformat:ssf:Some Script Format
+ const char *mime_description = m_NP_GetMIMEDescription();
+ if(!initializeMIMEDescription(mime_description)) {
+ PLUGIN_LOG("Bad MIME description: \"%s\"\n",
+ mime_description);
+ return false;
+ }
+
+ // Create a new Java Plugin object.
+ jobject pluginObject = createPluginObject(name,
+ m_path.utf8().data(),
+ m_fileName.utf8().data(),
+ description);
+ if(!pluginObject) {
+ PLUGIN_LOG("Couldn't create Java Plugin\n");
+ return false;
+ }
+
+ // Provide the plugin with our browser function table and grab its
+ // plugin table. Provide the Java environment and the Plugin which
+ // can be used to override the defaults if the plugin wants.
+ initializeBrowserFuncs();
+ memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs));
+ m_pluginFuncs.size = sizeof(m_pluginFuncs);
+ if(m_NP_Initialize(&m_browserFuncs,
+ &m_pluginFuncs,
+ m_env,
+ pluginObject) != NPERR_NO_ERROR) {
+ PLUGIN_LOG("Couldn't initialize plugin\n");
+ return false;
+ }
+
+ // Add the Plugin to the PluginList
+ jobject pluginListObject = getPluginListObject();
+ if(!pluginListObject) {
+ PLUGIN_LOG("Couldn't get PluginList object\n");
+ m_NP_Shutdown();
+ return false;
+ }
+ if(!addPluginObjectToList(pluginListObject, pluginObject)) {
+ PLUGIN_LOG("Couldn't add Plugin to PluginList\n");
+ m_NP_Shutdown();
+ return false;
+ }
+
+ // Retain the Java Plugin object
+ m_pluginObject = m_env->NewGlobalRef(pluginObject);
+
+ // Need to call NP_Shutdown at some point in the future.
+ m_libraryInitialized = true;
+
+ // Don't close the library - loaded OK.
+ dlCloser.ok();
+ // Retain the handle so we can close it in the future.
+ m_libraryHandle = handle;
+
+ PLUGIN_LOG("Loaded OK\n");
+ return true;
+}
+
+void PluginPackageAndroid::unload()
+{
+ if(!m_libraryHandle) {
+ PLUGIN_LOG("Plugin \"%s\" already unloaded\n", m_path.utf8().data());
+ return; // No library loaded
+ }
+ PLUGIN_LOG("Unloading \"%s\"\n", m_path.utf8().data());
+
+ if(m_libraryInitialized) {
+ // Shutdown the plug-in
+ ASSERT(m_NP_Shutdown != NULL);
+ PLUGIN_LOG("Calling NP_Shutdown\n");
+ NPError err = m_NP_Shutdown();
+ if(err != NPERR_NO_ERROR)
+ PLUGIN_LOG("Couldn't shutdown plug-in \"%s\"\n",
+ m_path.utf8().data());
+ m_libraryInitialized = false;
+
+ // Remove the plugin from the PluginList
+ if(m_pluginObject) {
+ jobject pluginListObject = getPluginListObject();
+ if(pluginListObject) {
+ removePluginObjectFromList(pluginListObject, m_pluginObject);
+ }
+ // Remove a reference to the Plugin object so it can
+ // garbage collect.
+ m_env->DeleteGlobalRef(m_pluginObject);
+ m_pluginObject = 0;
+ }
+ }
+
+ PLUGIN_LOG("Closing library\n");
+ dlclose(m_libraryHandle);
+ m_libraryHandle = 0;
+ memset(&m_browserFuncs, 0, sizeof(m_browserFuncs));
+ memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs));
+ m_NP_Initialize = 0;
+ m_NP_Shutdown = 0;
+ m_NP_GetMIMEDescription = 0;
+ m_NP_GetValue = 0;
+}
+
+const NPPluginFuncs* PluginPackageAndroid::pluginFuncs() const
+{
+ ASSERT(m_libraryHandle && m_libraryInitialized);
+ return &m_pluginFuncs;
+}
+
+PluginPackageAndroid* PluginPackageAndroid::createPackage(const String& path,
+ uint32 lastModified)
+{
+ PluginPackageAndroid* package = new PluginPackageAndroid(path,
+ lastModified);
+
+ if (!package->load()) {
+ delete package;
+ return 0;
+ }
+
+ return package;
+}
+
+bool PluginPackageAndroid::getEntryPoint(const char *name, void **entry_point)
+{
+ dlerror();
+ *entry_point = dlsym(m_libraryHandle, name);
+ const char *error = dlerror();
+ if(error == NULL && *entry_point != NULL) {
+ return true;
+ } else {
+ PLUGIN_LOG("Couldn't get entry point \"%s\": %s\n",
+ name, error);
+ return false;
+ }
+}
+
+bool PluginPackageAndroid::initializeMIMEEntry(const String& mimeEntry)
+{
+ // Each part is split into 3 fields separated by colons
+ // Field 1 is the MIME type (e.g "application/x-shockwave-flash").
+ // Field 2 is a comma separated list of file extensions.
+ // Field 3 is a human readable short description.
+ Vector<String> fields = mimeEntry.split(':', true);
+ if(fields.size() != 3)
+ return false;
+
+ const String& mimeType = fields[0];
+ Vector<String> extensions = fields[1].split(',', true);
+ const String& description = fields[2];
+
+ PLUGIN_LOG("mime_type: \"%s\"\n",
+ mimeType.utf8().data());
+ PLUGIN_LOG("extensions: \"%s\"\n",
+ fields[1].utf8().data());
+ PLUGIN_LOG("description: \"%s\"\n",
+ description.utf8().data());
+
+ // Map the mime type to the vector of extensions and the description
+ if(!extensions.isEmpty())
+ m_mimeToExtensions.set(mimeType, extensions);
+ if(!description.isEmpty())
+ m_mimeToDescriptions.set(mimeType, description);
+
+ return true;
+}
+
+bool PluginPackageAndroid::initializeMIMEDescription(
+ const String& mimeDescription)
+{
+ PLUGIN_LOG("MIME description: \"%s\"\n", mimeDescription.utf8().data());
+
+ // Clear out the current mappings.
+ m_mimeToDescriptions.clear();
+ m_mimeToExtensions.clear();
+
+ // Split the description into its component entries, separated by
+ // semicolons.
+ Vector<String> mimeEntries = mimeDescription.split(';', true);
+
+ // Iterate through the entries, adding them to the MIME mappings.
+ for(Vector<String>::const_iterator it = mimeEntries.begin();
+ it != mimeEntries.end(); ++it) {
+ if(!initializeMIMEEntry(*it)) {
+ PLUGIN_LOG("Bad MIME entry: \"%s\"\n", it->utf8().data());
+ m_mimeToDescriptions.clear();
+ m_mimeToExtensions.clear();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+PluginPackageAndroid::DynamicLibraryCloser::~DynamicLibraryCloser()
+{
+ // Close the PluginPackageAndroid's library
+ if(m_package)
+ {
+ if(m_package->m_libraryHandle)
+ {
+ dlclose(m_package->m_libraryHandle);
+ m_package->m_libraryHandle = NULL;
+ }
+ m_package = NULL;
+ }
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/plugins/android/PluginPackageAndroid.h b/WebCore/plugins/android/PluginPackageAndroid.h
new file mode 100644
index 0000000..d78df1e
--- /dev/null
+++ b/WebCore/plugins/android/PluginPackageAndroid.h
@@ -0,0 +1,152 @@
+#ifdef ANDROID_PLUGINS
+
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 PluginPackageAndroid_H
+#define PluginPackageAndroid_H
+
+#include "PlatformString.h"
+#include "StringHash.h"
+#include "Timer.h"
+#include "npfunctions.h"
+#include <wtf/HashMap.h>
+#include "wtf/RefCounted.h"
+
+namespace WebCore {
+ typedef HashMap<String, String> MIMEToDescriptionsMap;
+ typedef HashMap<String, Vector<String> > MIMEToExtensionsMap;
+
+ class PluginPackageAndroid : public RefCounted<PluginPackageAndroid> {
+ public:
+ ~PluginPackageAndroid();
+ static PluginPackageAndroid* createPackage(const String& path,
+ uint32 lastModified);
+
+ String path() const { return m_path; }
+ String name() const { return m_name; }
+ String fileName() const { return m_fileName; }
+ String description() const { return m_description; }
+ uint32 getLastModified() const { return m_lastModified; }
+
+ const MIMEToDescriptionsMap& mimeToDescriptions() const {
+ return m_mimeToDescriptions;
+ }
+ const MIMEToExtensionsMap& mimeToExtensions() const {
+ return m_mimeToExtensions;
+ }
+
+ bool load();
+ void unload();
+
+ const NPPluginFuncs* pluginFuncs() const;
+
+ private:
+ // Simple class which calls dlclose() on a dynamic library when going
+ // out of scope. Call ok() if the handle should stay open.
+ class DynamicLibraryCloser
+ {
+ public:
+ DynamicLibraryCloser(PluginPackageAndroid *package)
+ : m_package(package) { }
+ ~DynamicLibraryCloser();
+ void ok() { m_package = NULL; }
+ private:
+ PluginPackageAndroid *m_package;
+ };
+ friend class DynamicLibraryCloser;
+
+ PluginPackageAndroid(const String& path,
+ uint32 lastModified);
+
+ // Set all the NPN function pointers in m_browserFuncs
+ void initializeBrowserFuncs();
+
+ // Call dlsym() and set *entry_point to the return value for
+ // the symbol 'name'. Return true if the symbol exists.
+ bool getEntryPoint(const char *name, void **entry_point);
+
+ // Initialize m_mimeToDescriptions and m_mimeToExtensions from
+ // this individual MIME entry. If badly formatted, returns
+ // false.
+ bool initializeMIMEEntry(const String& mime_entry);
+
+ // Splits the MIME description into its entries and passes
+ // them to initializeMIMEEntry. Returns false if any of the
+ // description is badly format.
+ bool initializeMIMEDescription(const String& mime_description);
+
+ // Create a Java Plugin object instance
+ jobject createPluginObject(const char *name,
+ const char *path,
+ const char *fileName,
+ const char *description);
+
+ // Get hold of the Java PluginList instance.
+ jobject getPluginListObject();
+
+ // Add the plugin to the PluginList.
+ bool addPluginObjectToList(jobject pluginList,
+ jobject plugin);
+
+ // Remove the plugin from the Pluginlist
+ void removePluginObjectFromList(jobject pluginList,
+ jobject plugin);
+
+ String m_path; // Path to open this library
+ String m_name; // Human readable name e.g "Shockwave Flash"
+ String m_fileName; // Name of the file e.g "libflashplayer.so"
+ String m_description; // Verbose string e.g "Shockwave Flash 9.0 r48"
+ uint32 m_lastModified; // Last modification time, Unix seconds.
+
+ NPNetscapeFuncs m_browserFuncs;
+ NPPluginFuncs m_pluginFuncs;
+ MIMEToDescriptionsMap m_mimeToDescriptions;
+ MIMEToExtensionsMap m_mimeToExtensions;
+
+ // The Java environment.
+ JNIEnv *m_env;
+
+ // The Java Plugin object.
+ jobject m_pluginObject;
+
+ // Handle to the dynamic library. Non-NULL if open.
+ void *m_libraryHandle;
+
+ // True if the library is in the initialized state
+ // (NP_Initialize called)
+ bool m_libraryInitialized;
+
+ // Entry points into the library obtained using dlsym()
+ NP_InitializeFuncPtr m_NP_Initialize;
+ NP_ShutdownFuncPtr m_NP_Shutdown;
+ NP_GetMIMEDescriptionFuncPtr m_NP_GetMIMEDescription;
+ NP_GetValueFuncPtr m_NP_GetValue;
+ };
+} // namespace WebCore
+
+#endif
+
+#endif
diff --git a/WebCore/plugins/android/PluginViewAndroid.cpp b/WebCore/plugins/android/PluginViewAndroid.cpp
new file mode 100644
index 0000000..87dbe11
--- /dev/null
+++ b/WebCore/plugins/android/PluginViewAndroid.cpp
@@ -0,0 +1,567 @@
+#ifdef ANDROID_PLUGINS
+
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
+ */
+
+#include "config.h"
+#include "PluginViewAndroid.h"
+
+#include "Document.h"
+#include "Element.h"
+#include "FrameLoader.h"
+#include "FrameLoadRequest.h"
+#include "FrameTree.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HTMLNames.h"
+#include "HTMLPlugInElement.h"
+#include "Image.h"
+#include "MIMETypeRegistry.h"
+#include "NotImplemented.h"
+#include "Page.h"
+#include "PlatformGraphicsContext.h"
+#include "PluginPackageAndroid.h"
+#include "kjs_binding.h"
+#include "kjs_proxy.h"
+#include "kjs_window.h"
+#include "android_graphics.h"
+#include "SkCanvas.h"
+#include "npruntime_impl.h"
+#include "runtime_root.h"
+#include "Settings.h"
+#include <kjs/JSLock.h>
+#include <kjs/value.h>
+#include <wtf/ASCIICType.h>
+#include "runtime.h"
+#include "WebViewCore.h"
+
+#include "PluginDebug.h"
+
+using KJS::ExecState;
+using KJS::Interpreter;
+using KJS::JSLock;
+using KJS::JSObject;
+using KJS::JSValue;
+using KJS::UString;
+
+using std::min;
+
+using namespace WTF;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+PluginViewAndroid* PluginViewAndroid::s_currentPluginView = 0;
+
+void PluginViewAndroid::setParent(ScrollView* parent)
+{
+ if (parent)
+ init();
+}
+
+bool PluginViewAndroid::start()
+{
+ if (m_isStarted)
+ return false;
+
+ ASSERT(m_plugin);
+ ASSERT(m_plugin->pluginFuncs()->newp);
+
+ NPError npErr;
+ PluginViewAndroid::setCurrentPluginView(this);
+ {
+ KJS::JSLock::DropAllLocks dropAllLocks;
+ npErr = m_plugin->pluginFuncs()->newp((NPMIMEType)m_mimeType.data(),
+ m_instance,
+ m_mode,
+ m_paramCount,
+ m_paramNames,
+ m_paramValues,
+ NULL);
+ if(npErr)
+ PLUGIN_LOG("plugin->newp returned %d\n", static_cast<int>(npErr));
+ }
+ PluginViewAndroid::setCurrentPluginView(0);
+
+ if (npErr != NPERR_NO_ERROR)
+ return false;
+
+ m_isStarted = true;
+
+ return true;
+}
+
+void PluginViewAndroid::stop()
+{
+ if (!m_isStarted)
+ return;
+
+ m_isStarted = false;
+
+ KJS::JSLock::DropAllLocks dropAllLocks;
+
+ // Destroy the plugin
+ NPError npErr = m_plugin->pluginFuncs()->destroy(m_instance, 0);
+ if(npErr)
+ PLUGIN_LOG("Plugin destroy returned %d\n", static_cast<int>(npErr));
+
+ m_instance->pdata = 0;
+}
+
+void PluginViewAndroid::setCurrentPluginView(PluginViewAndroid* pluginView)
+{
+ s_currentPluginView = pluginView;
+}
+
+PluginViewAndroid* PluginViewAndroid::currentPluginView()
+{
+ return s_currentPluginView;
+}
+
+static char* createUTF8String(const String& str)
+{
+ CString cstr = str.utf8();
+ char* result = reinterpret_cast<char*>(fastMalloc(cstr.length() + 1));
+
+ strncpy(result, cstr.data(), cstr.length() + 1);
+
+ return result;
+}
+
+static void freeStringArray(char** stringArray, int length)
+{
+ if (!stringArray)
+ return;
+
+ for (int i = 0; i < length; i++)
+ fastFree(stringArray[i]);
+
+ fastFree(stringArray);
+}
+
+NPError PluginViewAndroid::getURLNotify(const char* url,
+ const char* target,
+ void* notifyData)
+{
+ notImplemented();
+ return NPERR_GENERIC_ERROR;
+}
+
+NPError PluginViewAndroid::getURL(const char* url, const char* target)
+{
+ notImplemented();
+ return NPERR_GENERIC_ERROR;
+}
+
+NPError PluginViewAndroid::postURLNotify(const char* url,
+ const char* target,
+ uint32 len,
+ const char* buf,
+ NPBool file,
+ void* notifyData)
+{
+ notImplemented();
+ return NPERR_GENERIC_ERROR;
+}
+
+NPError PluginViewAndroid::postURL(const char* url,
+ const char* target,
+ uint32 len,
+ const char* buf,
+ NPBool file)
+{
+ notImplemented();
+ return NPERR_GENERIC_ERROR;
+}
+
+NPError PluginViewAndroid::newStream(NPMIMEType type,
+ const char* target,
+ NPStream** stream)
+{
+ notImplemented();
+ return NPERR_GENERIC_ERROR;
+}
+
+int32 PluginViewAndroid::write(NPStream* stream,
+ int32 len,
+ void* buffer)
+{
+ notImplemented();
+ return -1;
+}
+
+NPError PluginViewAndroid::destroyStream(NPStream* stream, NPReason reason)
+{
+ notImplemented();
+ return NPERR_GENERIC_ERROR;
+}
+
+const char* PluginViewAndroid::userAgent()
+{
+ if (m_userAgent.isNull())
+ m_userAgent = m_parentFrame->loader()->userAgent(m_url).utf8();
+ return m_userAgent.data();
+}
+
+void PluginViewAndroid::status(const char* message)
+{
+ String s = DeprecatedString::fromLatin1(message);
+
+ if (Page* page = m_parentFrame->page())
+ page->chrome()->setStatusbarText(m_parentFrame, s);
+}
+
+NPError PluginViewAndroid::getValue(NPNVariable variable, void* value)
+{
+ switch (variable) {
+ case NPNVWindowNPObject: {
+ NPObject* windowScriptObject =
+ m_parentFrame->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: {
+ NPObject* pluginScriptObject = 0;
+
+ if (m_element->hasTagName(appletTag) ||
+ m_element->hasTagName(embedTag) ||
+ m_element->hasTagName(objectTag)) {
+ HTMLPlugInElement* pluginElement =
+ static_cast<HTMLPlugInElement*>(m_element);
+ pluginScriptObject = pluginElement->getNPObject();
+ }
+
+ // Return value is expected to be retained, as described
+ // here:
+ // <http://www.mozilla.org/projects/plugin/npruntime.html>
+ if (pluginScriptObject)
+ _NPN_RetainObject(pluginScriptObject);
+
+ void** v = (void**)value;
+ *v = pluginScriptObject;
+
+ return NPERR_NO_ERROR;
+ }
+
+ case NPNVnetscapeWindow: {
+ // Return the top level WebView Java object associated
+ // with this instance.
+ jobject *retObject = static_cast<jobject*>(value);
+ // Dig down through to the parent frame's WebCoreViewBridge
+ FrameView* frameView = m_parentFrame->view();
+ WebCoreViewBridge* bridge = frameView->getWebCoreViewBridge();
+ // Go up parents until we reach the top level.
+ while (bridge->getParent() != NULL)
+ bridge = bridge->getParent();
+ // This is actually an instance of WebCoreView.
+ android::WebViewCore* webViewCore =
+ static_cast<android::WebViewCore*>(bridge);
+ // Finally, get hold of the Java WebView instance.
+ *retObject = webViewCore->getWebViewJavaObject();
+ return NPERR_NO_ERROR;
+ }
+ default:
+ return NPERR_GENERIC_ERROR;
+ }
+}
+
+NPError PluginViewAndroid::setValue(NPPVariable variable, void* value)
+{
+ switch (variable) {
+ case NPPVpluginWindowBool:
+ m_isWindowed = value;
+ return NPERR_NO_ERROR;
+ case NPPVpluginTransparentBool:
+ m_isTransparent = value;
+ return NPERR_NO_ERROR;
+ default:
+ notImplemented();
+ return NPERR_GENERIC_ERROR;
+ }
+}
+
+void PluginViewAndroid::invalidateRect(NPRect* rect)
+{
+ notImplemented();
+}
+
+void PluginViewAndroid::invalidateRegion(NPRegion region)
+{
+ notImplemented();
+}
+
+void PluginViewAndroid::forceRedraw()
+{
+ notImplemented();
+}
+
+KJS::Bindings::Instance* PluginViewAndroid::bindingInstance()
+{
+ NPObject* object = 0;
+
+ if (!m_plugin || !m_plugin->pluginFuncs()->getvalue)
+ return 0;
+
+ NPError npErr;
+ {
+ KJS::JSLock::DropAllLocks dropAllLocks;
+ npErr = m_plugin->pluginFuncs()->getvalue(m_instance,
+ NPPVpluginScriptableNPObject,
+ &object);
+ }
+
+ if (npErr != NPERR_NO_ERROR || !object)
+ return 0;
+
+ RefPtr<KJS::Bindings::RootObject> root = m_parentFrame->createRootObject(
+ this,
+ m_parentFrame->scriptProxy()->globalObject());
+ KJS::Bindings::Instance *instance =
+ KJS::Bindings::Instance::createBindingForLanguageInstance(
+ KJS::Bindings::Instance::CLanguage,
+ object,
+ root.release());
+
+ _NPN_ReleaseObject(object);
+
+ return instance;
+}
+
+PluginViewAndroid::~PluginViewAndroid()
+{
+ stop();
+
+ freeStringArray(m_paramNames, m_paramCount);
+ freeStringArray(m_paramValues, m_paramCount);
+
+ m_parentFrame->cleanupScriptObjectsForPlugin(this);
+
+ // Don't unload the plugin - let the reference count clean it up.
+
+ // Can't use RefPtr<> because it's name clashing with SkRefCnt<>
+ m_viewBridge->unref();
+}
+
+void PluginViewAndroid::setParameters(const Vector<String>& paramNames,
+ const Vector<String>& paramValues)
+{
+ ASSERT(paramNames.size() == paramValues.size());
+
+ // Also pass an extra parameter
+ unsigned size = paramNames.size() + 1;
+ unsigned paramCount = 0;
+
+ m_paramNames = reinterpret_cast<char**>(fastMalloc(sizeof(char*) * size));
+ m_paramValues = reinterpret_cast<char**>(fastMalloc(sizeof(char*) * size));
+
+ for (unsigned i = 0; i < paramNames.size(); i++) {
+ if (equalIgnoringCase(paramNames[i], "windowlessvideo"))
+ continue;
+ // Don't let the HTML element specify this value!
+ if (equalIgnoringCase(paramNames[i], "android_plugins_dir"))
+ continue;
+
+ m_paramNames[paramCount] = createUTF8String(paramNames[i]);
+ m_paramValues[paramCount] = createUTF8String(paramValues[i]);
+
+ paramCount++;
+ }
+
+ // Pass the location of the plug-ins directory so the plug-in
+ // knows where it can store any data it needs.
+ WebCore::String path = m_parentFrame->settings()->pluginsPath();
+ m_paramNames[paramCount] = createUTF8String("android_plugins_dir");
+ m_paramValues[paramCount] = createUTF8String(path.utf8().data());
+ paramCount++;
+
+ m_paramCount = paramCount;
+}
+
+PluginViewAndroid::PluginViewAndroid(Frame* parentFrame,
+ const IntSize& size,
+ PluginPackageAndroid* plugin,
+ Element* element,
+ const KURL& url,
+ const Vector<String>& paramNames,
+ const Vector<String>& paramValues,
+ const String& mimeType,
+ bool loadManually)
+ : m_plugin(plugin)
+ , m_element(element)
+ , m_parentFrame(parentFrame)
+ , m_userAgent()
+ , m_isStarted(false)
+ , m_url(url)
+ , m_status(PluginStatusLoadedSuccessfully)
+ , m_mode(0)
+ , m_paramCount(0)
+ , m_paramNames(0)
+ , m_paramValues(0)
+ , m_mimeType()
+ , m_instance()
+ , m_instanceStruct()
+ , m_isWindowed(true)
+ , m_isTransparent(false)
+ , m_haveInitialized(false)
+ , m_lastMessage(0)
+ , m_loadManually(loadManually)
+ , m_viewBridge(new PluginViewBridgeAndroid())
+{
+ setWebCoreViewBridge(m_viewBridge);
+
+ if (!m_plugin) {
+ m_status = PluginStatusCanNotFindPlugin;
+ return;
+ }
+
+ m_instance = &m_instanceStruct;
+ m_instance->ndata = this;
+
+ m_mimeType = mimeType.utf8();
+
+ setParameters(paramNames, paramValues);
+
+ m_mode = m_loadManually ? NP_FULL : NP_EMBED;
+
+ resize(size);
+
+ // Early initialisation until we can properly parent this
+ init();
+}
+
+void PluginViewAndroid::init()
+{
+ if (m_haveInitialized)
+ return;
+ m_haveInitialized = true;
+
+ if (!m_plugin) {
+ ASSERT(m_status == PluginStatusCanNotFindPlugin);
+ return;
+ }
+
+ if (!m_plugin->load()) {
+ m_plugin = 0;
+ m_status = PluginStatusCanNotLoadPlugin;
+ return;
+ }
+
+ if (!start()) {
+ m_status = PluginStatusCanNotLoadPlugin;
+ return;
+ }
+
+ m_status = PluginStatusLoadedSuccessfully;
+}
+
+PluginViewBridgeAndroid::PluginViewBridgeAndroid()
+{
+ m_image = Image::loadPlatformResource("nullplugin");
+ if(m_image)
+ setSize(m_image->width(), m_image->height());
+ else
+ PLUGIN_LOG("Couldn't get nullplugin image\n");
+}
+
+PluginViewBridgeAndroid::~PluginViewBridgeAndroid()
+{
+ delete m_image;
+}
+
+void PluginViewBridgeAndroid::draw(GraphicsContext* gc,
+ const IntRect& rect,
+ bool)
+{
+ if (gc->paintingDisabled() || !m_image)
+ return;
+
+ // Clip the drawing rectangle to our bounds in case it is larger.
+ IntRect transRect(rect);
+ IntRect bounds = this->getBounds();
+ transRect.intersect(bounds);
+
+ // Move the drawing rectangle into our coordinate space.
+ transRect.move(-bounds.x(), -bounds.y());
+
+ // Translate the canvas by the view's location so that things will draw
+ // in the right place. Clip the canvas to the drawing rectangle.
+ SkRect r;
+ android_setrect(&r, transRect);
+ if (r.isEmpty())
+ return;
+ SkCanvas* canvas = gc->platformContext()->mCanvas;
+ canvas->save();
+ canvas->translate(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()));
+ canvas->clipRect(r);
+
+ // Calculate where to place the image so it appears in the center of the
+ // view.
+ int imageWidth = m_image->width();
+ int imageHeight = m_image->height();
+ IntRect centerRect(0, 0, imageWidth, imageHeight);
+ IntSize c1(bounds.width()/2, bounds.height()/2);
+ IntSize c2(centerRect.width()/2, centerRect.height()/2);
+ IntSize diff = c1 - c2;
+ centerRect.move(diff);
+
+ // Now move the top-left corner of the image to the top-left corner of
+ // the view so that the tiling will hit the center image.
+ while (diff.width() > 0)
+ diff.setWidth(diff.width() - imageWidth);
+ while (diff.height() > 0)
+ diff.setHeight(diff.height() - imageHeight);
+
+ // Draw the tiled transparent image adding one extra image width and
+ // height so that we get a complete fill.
+ gc->beginTransparencyLayer(0.1);
+ gc->drawTiledImage(m_image,
+ IntRect(diff.width(), diff.height(),
+ bounds.width() + imageWidth,
+ bounds.height() + imageHeight),
+ IntPoint(0, 0), IntSize(imageWidth, imageHeight));
+ gc->endTransparencyLayer();
+
+ // Draw the image in the center.
+ gc->drawImage(m_image, centerRect);
+
+ // Restore our canvas
+ canvas->restore();
+}
+
+} // namespace WebCore
+
+#endif // defined(ANDROID_PLUGINS)
diff --git a/WebCore/plugins/android/PluginViewAndroid.h b/WebCore/plugins/android/PluginViewAndroid.h
new file mode 100644
index 0000000..d4e55b8
--- /dev/null
+++ b/WebCore/plugins/android/PluginViewAndroid.h
@@ -0,0 +1,176 @@
+#ifdef ANDROID_PLUGINS
+
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 PluginViewAndroid_H
+#define PluginViewAndroid_H
+
+#include "CString.h"
+#include "IntRect.h"
+#include "KURL.h"
+#include "PlatformString.h"
+#include "ResourceRequest.h"
+#include "Widget.h"
+#include "npapi.h"
+#include "WebCoreViewBridge.h"
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace KJS {
+ namespace Bindings {
+ class Instance;
+ }
+}
+
+namespace WebCore {
+ class Element;
+ class Frame;
+ class Image;
+ class KURL;
+ class PluginPackageAndroid;
+
+ enum PluginStatus {
+ PluginStatusCanNotFindPlugin,
+ PluginStatusCanNotLoadPlugin,
+ PluginStatusLoadedSuccessfully
+ };
+
+ class PluginViewBridgeAndroid : public WebCoreViewBridge {
+ public:
+ PluginViewBridgeAndroid();
+ ~PluginViewBridgeAndroid();
+ virtual void draw(GraphicsContext* gc, const IntRect& rect, bool);
+ private:
+ Image* m_image;
+ };
+
+ class PluginViewAndroid : public Widget {
+ public:
+ PluginViewAndroid(Frame* parentFrame,
+ const IntSize&,
+ PluginPackageAndroid* plugin,
+ Element*,
+ const KURL&,
+ const Vector<String>& paramNames,
+ const Vector<String>& paramValues,
+ const String& mimeType,
+ bool loadManually);
+ virtual ~PluginViewAndroid();
+
+ PluginPackageAndroid* plugin() const { return m_plugin.get(); }
+ NPP instance() const { return m_instance; }
+
+ static PluginViewAndroid* currentPluginView();
+
+ KJS::Bindings::Instance* bindingInstance();
+
+ PluginStatus status() const { return m_status; }
+
+ // NPN stream functions
+ NPError getURLNotify(const char* url,
+ const char* target,
+ void* notifyData);
+ NPError getURL(const char* url,
+ const char* target);
+ NPError postURLNotify(const char* url,
+ const char* target,
+ uint32 len,
+ const char* but,
+ NPBool file,
+ void* notifyData);
+ NPError postURL(const char* url,
+ const char* target,
+ uint32 len,
+ const char* but,
+ NPBool file);
+ NPError newStream(NPMIMEType type,
+ const char* target,
+ NPStream** stream);
+ int32 write(NPStream* stream, int32 len, void* buffer);
+ NPError destroyStream(NPStream* stream, NPReason reason);
+
+ // NPN misc functions
+ const char* userAgent();
+ void status(const char* message);
+ NPError getValue(NPNVariable variable, void* value);
+ NPError setValue(NPPVariable variable, void* value);
+
+ // NPN UI functions
+ void invalidateRect(NPRect*);
+ void invalidateRegion(NPRegion);
+ void forceRedraw();
+
+ // Widget functions
+ virtual void setParent(ScrollView*);
+
+ private:
+ void setParameters(const Vector<String>& paramNames,
+ const Vector<String>& paramValues);
+ void init();
+ bool start();
+ void stop();
+ static void setCurrentPluginView(PluginViewAndroid*);
+
+ // Maintain a refcount on the plugin. It should be deleted
+ // once all views no longer reference it.
+ RefPtr<PluginPackageAndroid> m_plugin;
+ Element* m_element;
+ Frame* m_parentFrame;
+ CString m_userAgent;
+ bool m_isStarted;
+ KURL m_url;
+ PluginStatus m_status;
+
+ int m_mode;
+ int m_paramCount;
+ char** m_paramNames;
+ char** m_paramValues;
+
+ CString m_mimeType;
+ NPP m_instance;
+ NPP_t m_instanceStruct;
+
+ bool m_isWindowed;
+ bool m_isTransparent;
+ bool m_haveInitialized;
+
+ unsigned m_lastMessage;
+
+ bool m_loadManually;
+
+ // Sorry, can't use RefPtr<> due to name collision with SkRefCnt.
+ PluginViewBridgeAndroid *m_viewBridge;
+
+ static PluginViewAndroid* s_currentPluginView;
+ };
+
+} // namespace WebCore
+
+#endif
+
+#endif // defined(ANDROID_PLUGINS)
diff --git a/WebCore/plugins/android/npapi.cpp b/WebCore/plugins/android/npapi.cpp
new file mode 100644
index 0000000..23007eb
--- /dev/null
+++ b/WebCore/plugins/android/npapi.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
+ */
+
+#include "config.h"
+
+#ifdef ANDROID_PLUGINS
+// Needed for NPN_PluginThreadAsyncCall, which calls
+// JavaSharedClient::EnqueueFunctionPtr().
+#include "JavaSharedClient.h"
+#endif
+#include "WebCoreJni.h"
+#include "PluginInfoStore.h"
+#include "PluginViewAndroid.h"
+#include "jni.h"
+#include "npapi.h"
+
+#include "PluginDebug.h"
+
+using namespace WebCore;
+
+// The plugin view is always the ndata of the instance,. Sometimes, plug-ins will call an instance-specific function
+// with a NULL instance. To workaround this, call the last plug-in view that made a call to a plug-in.
+// Currently, the current plug-in view is only set before NPP_New in PluginViewAndroid::start.
+// This specifically works around Flash and Shockwave. When we call NPP_New, they call NPN_Useragent with a NULL instance.
+static PluginViewAndroid* pluginViewForInstance(NPP instance)
+{
+ if (instance && instance->ndata)
+ return static_cast<PluginViewAndroid*>(instance->ndata);
+ return PluginViewAndroid::currentPluginView();
+}
+
+void* NPN_MemAlloc(uint32 size)
+{
+ return malloc(size);
+}
+
+void NPN_MemFree(void* ptr)
+{
+ free(ptr);
+}
+
+uint32 NPN_MemFlush(uint32 size)
+{
+ // Do nothing
+ return 0;
+}
+
+void NPN_ReloadPlugins(NPBool reloadPages)
+{
+ refreshPlugins(reloadPages);
+}
+
+NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList)
+{
+ return NPERR_STREAM_NOT_SEEKABLE;
+}
+
+NPError NPN_GetURLNotify(NPP instance, const char* url, const char* target, void* notifyData)
+{
+ return pluginViewForInstance(instance)->getURLNotify(url, target, notifyData);
+}
+
+NPError NPN_GetURL(NPP instance, const char* url, const char* target)
+{
+ return pluginViewForInstance(instance)->getURL(url, target);
+}
+
+NPError NPN_PostURLNotify(NPP instance, const char* url, const char* target, uint32 len, const char* buf, NPBool file, void* notifyData)
+{
+ return pluginViewForInstance(instance)->postURLNotify(url, target, len, buf, file, notifyData);
+}
+
+NPError NPN_PostURL(NPP instance, const char* url, const char* target, uint32 len, const char* buf, NPBool file)
+{
+ return pluginViewForInstance(instance)->postURL(url, target, len, buf, file);
+}
+
+NPError NPN_NewStream(NPP instance, NPMIMEType type, const char* target, NPStream** stream)
+{
+ return pluginViewForInstance(instance)->newStream(type, target, stream);
+}
+
+int32 NPN_Write(NPP instance, NPStream* stream, int32 len, void* buffer)
+{
+ return pluginViewForInstance(instance)->write(stream, len, buffer);
+}
+
+NPError NPN_DestroyStream(NPP instance, NPStream* stream, NPReason reason)
+{
+ return pluginViewForInstance(instance)->destroyStream(stream, reason);
+}
+
+const char* NPN_UserAgent(NPP instance)
+{
+ PluginViewAndroid* view = pluginViewForInstance(instance);
+
+ // FIXME: Some plug-ins call NPN_UserAgent with a null instance in their NP_initialize function!
+ // We'd need a way to get a user agent without having a frame around.
+ if (!view)
+ return 0;
+
+ return view->userAgent();
+}
+
+void NPN_Status(NPP instance, const char* message)
+{
+ pluginViewForInstance(instance)->status(message);
+}
+
+void NPN_InvalidateRect(NPP instance, NPRect* invalidRect)
+{
+ pluginViewForInstance(instance)->invalidateRect(invalidRect);
+}
+
+void NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion)
+{
+ pluginViewForInstance(instance)->invalidateRegion(invalidRegion);
+}
+
+void NPN_ForceRedraw(NPP instance)
+{
+ pluginViewForInstance(instance)->forceRedraw();
+}
+
+NPError NPN_GetValue(NPP instance, NPNVariable variable, void* value)
+{
+ return pluginViewForInstance(instance)->getValue(variable, value);
+}
+
+NPError NPN_SetValue(NPP instance, NPPVariable variable, void* value)
+{
+ return pluginViewForInstance(instance)->setValue(variable, value);
+}
+
+void* NPN_GetJavaEnv()
+{
+ // This is supposed to return the JRIEnv, but nobody's been using
+ // that interface for years. Far more useful to return the JNIEnv,
+ // so we'll do that...
+ JNIEnv* env = NULL;
+ if (android::WebCoreJni::getJavaVM()->GetEnv((void**) &env,
+ JNI_VERSION_1_4) != JNI_OK) {
+ PLUGIN_LOG("GetEnv failed!");
+ }
+ return env;
+}
+
+void* NPN_GetJavaPeer(NPP instance)
+{
+ // Unsupported
+ return 0;
+}
+
+void
+NPN_PushPopupsEnabledState(NPP instance, NPBool enabled)
+{
+}
+
+void
+NPN_PopPopupsEnabledState(NPP instance)
+{
+}
+
+#ifdef ANDROID_PLUGINS
+// Added in version 19 NPAPI. Sandbox WebKit has this same function in
+// plugins/npapi.cpp rather than plugins/android/npapi.cpp. This file
+// goes away after merge.
+void NPN_PluginThreadAsyncCall(NPP instance,
+ void (*func)(void *),
+ void *userData)
+{
+ // This is used to marshal a function call onto the main thread,
+ // so plugins can get around not "owning" the message loop. Note
+ // that the plugin is responsible for taking care of the potential
+ // race between the order of NPP_Destroy and callbacks.
+ JavaSharedClient::EnqueueFunctionPtr(func, userData);
+}
+#endif
diff --git a/WebCore/plugins/android/npfunctions.h b/WebCore/plugins/android/npfunctions.h
new file mode 100644
index 0000000..f9a5612
--- /dev/null
+++ b/WebCore/plugins/android/npfunctions.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2007 Apple Inc. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 _NPFUNCTIONS_H_
+#define _NPFUNCTIONS_H_
+
+#include <jni.h>
+#include "npruntime.h"
+#include "npapi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(XP_WIN)
+#define EXPORTED_CALLBACK(_type, _name) _type (__stdcall * _name)
+#else
+#define EXPORTED_CALLBACK(_type, _name) _type (* _name)
+#endif
+
+typedef NPError (*NPN_GetURLNotifyProcPtr)(NPP instance, const char* URL, const char* window, void* notifyData);
+typedef NPError (*NPN_PostURLNotifyProcPtr)(NPP instance, const char* URL, const char* window, uint32 len, const char* buf, NPBool file, void* notifyData);
+typedef NPError (*NPN_RequestReadProcPtr)(NPStream* stream, NPByteRange* rangeList);
+typedef NPError (*NPN_NewStreamProcPtr)(NPP instance, NPMIMEType type, const char* window, NPStream** stream);
+typedef int32 (*NPN_WriteProcPtr)(NPP instance, NPStream* stream, int32 len, void* buffer);
+typedef NPError (*NPN_DestroyStreamProcPtr)(NPP instance, NPStream* stream, NPReason reason);
+typedef void (*NPN_StatusProcPtr)(NPP instance, const char* message);
+typedef const char*(*NPN_UserAgentProcPtr)(NPP instance);
+typedef void* (*NPN_MemAllocProcPtr)(uint32 size);
+typedef void (*NPN_MemFreeProcPtr)(void* ptr);
+typedef uint32 (*NPN_MemFlushProcPtr)(uint32 size);
+typedef void (*NPN_ReloadPluginsProcPtr)(NPBool reloadPages);
+typedef NPError (*NPN_GetValueProcPtr)(NPP instance, NPNVariable variable, void *ret_value);
+typedef NPError (*NPN_SetValueProcPtr)(NPP instance, NPPVariable variable, void *value);
+typedef void (*NPN_InvalidateRectProcPtr)(NPP instance, NPRect *rect);
+typedef void (*NPN_InvalidateRegionProcPtr)(NPP instance, NPRegion region);
+typedef void (*NPN_ForceRedrawProcPtr)(NPP instance);
+typedef NPError (*NPN_GetURLProcPtr)(NPP instance, const char* URL, const char* window);
+typedef NPError (*NPN_PostURLProcPtr)(NPP instance, const char* URL, const char* window, uint32 len, const char* buf, NPBool file);
+typedef void* (*NPN_GetJavaEnvProcPtr)(void);
+typedef void* (*NPN_GetJavaPeerProcPtr)(NPP instance);
+typedef void (*NPN_PushPopupsEnabledStateProcPtr)(NPP instance, NPBool enabled);
+typedef void (*NPN_PopPopupsEnabledStateProcPtr)(NPP instance);
+
+typedef void (*NPN_ReleaseVariantValueProcPtr) (NPVariant *variant);
+
+typedef NPIdentifier (*NPN_GetStringIdentifierProcPtr) (const NPUTF8 *name);
+typedef void (*NPN_GetStringIdentifiersProcPtr) (const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers);
+typedef NPIdentifier (*NPN_GetIntIdentifierProcPtr) (int32_t intid);
+typedef int32_t (*NPN_IntFromIdentifierProcPtr) (NPIdentifier identifier);
+typedef bool (*NPN_IdentifierIsStringProcPtr) (NPIdentifier identifier);
+typedef NPUTF8 *(*NPN_UTF8FromIdentifierProcPtr) (NPIdentifier identifier);
+
+typedef NPObject* (*NPN_CreateObjectProcPtr) (NPP, NPClass *aClass);
+typedef NPObject* (*NPN_RetainObjectProcPtr) (NPObject *obj);
+typedef void (*NPN_ReleaseObjectProcPtr) (NPObject *obj);
+typedef bool (*NPN_InvokeProcPtr) (NPP npp, NPObject *obj, NPIdentifier methodName, const NPVariant *args, unsigned argCount, NPVariant *result);
+typedef bool (*NPN_InvokeDefaultProcPtr) (NPP npp, NPObject *obj, const NPVariant *args, unsigned argCount, NPVariant *result);
+typedef bool (*NPN_EvaluateProcPtr) (NPP npp, NPObject *obj, NPString *script, NPVariant *result);
+typedef bool (*NPN_GetPropertyProcPtr) (NPP npp, NPObject *obj, NPIdentifier propertyName, NPVariant *result);
+typedef bool (*NPN_SetPropertyProcPtr) (NPP npp, NPObject *obj, NPIdentifier propertyName, const NPVariant *value);
+typedef bool (*NPN_HasPropertyProcPtr) (NPP, NPObject *npobj, NPIdentifier propertyName);
+typedef bool (*NPN_HasMethodProcPtr) (NPP npp, NPObject *npobj, NPIdentifier methodName);
+typedef bool (*NPN_RemovePropertyProcPtr) (NPP npp, NPObject *obj, NPIdentifier propertyName);
+typedef void (*NPN_SetExceptionProcPtr) (NPObject *obj, const NPUTF8 *message);
+typedef bool (*NPN_EnumerateProcPtr) (NPP npp, NPObject *npobj, NPIdentifier **identifier, uint32_t *count);
+#ifdef ANDROID_PLUGINS
+// Added in version 19 NPAPI. Sandbox WebKit is version 20 and already
+// implements this change.
+typedef void (*NPN_PluginThreadAsyncCallPtr) (NPP npp, void (*func)(void *), void *userData);
+#endif
+
+typedef NPError (*NPP_NewProcPtr)(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved);
+typedef NPError (*NPP_DestroyProcPtr)(NPP instance, NPSavedData** save);
+typedef NPError (*NPP_SetWindowProcPtr)(NPP instance, NPWindow* window);
+typedef NPError (*NPP_NewStreamProcPtr)(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype);
+typedef NPError (*NPP_DestroyStreamProcPtr)(NPP instance, NPStream* stream, NPReason reason);
+typedef void (*NPP_StreamAsFileProcPtr)(NPP instance, NPStream* stream, const char* fname);
+typedef int32 (*NPP_WriteReadyProcPtr)(NPP instance, NPStream* stream);
+typedef int32 (*NPP_WriteProcPtr)(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer);
+typedef void (*NPP_PrintProcPtr)(NPP instance, NPPrint* platformPrint);
+typedef int16 (*NPP_HandleEventProcPtr)(NPP instance, void* event);
+typedef void (*NPP_URLNotifyProcPtr)(NPP instance, const char* URL, NPReason reason, void* notifyData);
+typedef NPError (*NPP_GetValueProcPtr)(NPP instance, NPPVariable variable, void *ret_value);
+typedef NPError (*NPP_SetValueProcPtr)(NPP instance, NPNVariable variable, void *value);
+typedef EXPORTED_CALLBACK(void, NPP_ShutdownProcPtr)(void);
+
+typedef void *(*NPP_GetJavaClassProcPtr)(void);
+typedef void* JRIGlobalRef; //not using this right now
+
+typedef struct _NPNetscapeFuncs {
+ uint16 size;
+ uint16 version;
+
+ NPN_GetURLProcPtr geturl;
+ NPN_PostURLProcPtr posturl;
+ NPN_RequestReadProcPtr requestread;
+ NPN_NewStreamProcPtr newstream;
+ NPN_WriteProcPtr write;
+ NPN_DestroyStreamProcPtr destroystream;
+ NPN_StatusProcPtr status;
+ NPN_UserAgentProcPtr uagent;
+ NPN_MemAllocProcPtr memalloc;
+ NPN_MemFreeProcPtr memfree;
+ NPN_MemFlushProcPtr memflush;
+ NPN_ReloadPluginsProcPtr reloadplugins;
+ NPN_GetJavaEnvProcPtr getJavaEnv;
+ NPN_GetJavaPeerProcPtr getJavaPeer;
+ NPN_GetURLNotifyProcPtr geturlnotify;
+ NPN_PostURLNotifyProcPtr posturlnotify;
+ NPN_GetValueProcPtr getvalue;
+ NPN_SetValueProcPtr setvalue;
+ NPN_InvalidateRectProcPtr invalidaterect;
+ NPN_InvalidateRegionProcPtr invalidateregion;
+ NPN_ForceRedrawProcPtr forceredraw;
+
+ NPN_GetStringIdentifierProcPtr getstringidentifier;
+ NPN_GetStringIdentifiersProcPtr getstringidentifiers;
+ NPN_GetIntIdentifierProcPtr getintidentifier;
+ NPN_IdentifierIsStringProcPtr identifierisstring;
+ NPN_UTF8FromIdentifierProcPtr utf8fromidentifier;
+ NPN_IntFromIdentifierProcPtr intfromidentifier;
+ NPN_CreateObjectProcPtr createobject;
+ NPN_RetainObjectProcPtr retainobject;
+ NPN_ReleaseObjectProcPtr releaseobject;
+ NPN_InvokeProcPtr invoke;
+ NPN_InvokeDefaultProcPtr invokeDefault;
+ NPN_EvaluateProcPtr evaluate;
+ NPN_GetPropertyProcPtr getproperty;
+ NPN_SetPropertyProcPtr setproperty;
+ NPN_RemovePropertyProcPtr removeproperty;
+ NPN_HasPropertyProcPtr hasproperty;
+ NPN_HasMethodProcPtr hasmethod;
+ NPN_ReleaseVariantValueProcPtr releasevariantvalue;
+ NPN_SetExceptionProcPtr setexception;
+ NPN_PushPopupsEnabledStateProcPtr pushpopupsenabledstate;
+ NPN_PopPopupsEnabledStateProcPtr poppopupsenabledstate;
+ NPN_EnumerateProcPtr enumerate;
+#ifdef ANDROID_PLUGINS
+ // Added in version 19 NPAPI. Sandbox WebKit is version 20 and
+ // already implements this change.
+ NPN_PluginThreadAsyncCallPtr pluginthreadasynccall;
+#endif
+} NPNetscapeFuncs;
+
+typedef struct _NPPluginFuncs {
+ uint16 size;
+ uint16 version;
+ NPP_NewProcPtr newp;
+ NPP_DestroyProcPtr destroy;
+ NPP_SetWindowProcPtr setwindow;
+ NPP_NewStreamProcPtr newstream;
+ NPP_DestroyStreamProcPtr destroystream;
+ NPP_StreamAsFileProcPtr asfile;
+ NPP_WriteReadyProcPtr writeready;
+ NPP_WriteProcPtr write;
+ NPP_PrintProcPtr print;
+ NPP_HandleEventProcPtr event;
+ NPP_URLNotifyProcPtr urlnotify;
+ JRIGlobalRef javaClass;
+ NPP_GetValueProcPtr getvalue;
+ NPP_SetValueProcPtr setvalue;
+} NPPluginFuncs;
+
+typedef NPError (*NP_InitializeFuncPtr)(NPNetscapeFuncs *netscape_funcs,
+ NPPluginFuncs *plugin_funcs,
+ JNIEnv *java_environment,
+ jobject application_context);
+typedef NPError (*NP_ShutdownFuncPtr)();
+typedef char* (*NP_GetMIMEDescriptionFuncPtr)();
+typedef NPError (*NP_GetValueFuncPtr)(void *instance,
+ NPPVariable var,
+ void *value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/WebCore/plugins/win/PluginDatabaseWin.cpp b/WebCore/plugins/win/PluginDatabaseWin.cpp
index 674de1e..be8a253 100644
--- a/WebCore/plugins/win/PluginDatabaseWin.cpp
+++ b/WebCore/plugins/win/PluginDatabaseWin.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,14 +26,99 @@
#include "config.h"
#include "PluginDatabase.h"
-#include "Frame.h"
-#include "KURL.h"
#include "PluginPackage.h"
+#include "PluginView.h"
+#include "Frame.h"
#include <windows.h>
#include <shlwapi.h>
namespace WebCore {
+PluginDatabase* PluginDatabase::installedPlugins()
+{
+ static PluginDatabase* plugins = 0;
+
+ if (!plugins) {
+ plugins = new PluginDatabase;
+ plugins->setPluginPaths(PluginDatabase::defaultPluginPaths());
+ plugins->refresh();
+ }
+
+ return plugins;
+}
+
+void PluginDatabase::addExtraPluginPath(const String& path)
+{
+ m_pluginPaths.append(path);
+ refresh();
+}
+
+bool PluginDatabase::refresh()
+{
+ PluginSet newPlugins;
+
+ bool pluginSetChanged = false;
+
+ // Create a new set of plugins
+ newPlugins = getPluginsInPaths();
+
+ if (!m_plugins.isEmpty()) {
+ m_registeredMIMETypes.clear();
+
+ PluginSet pluginsToUnload = m_plugins;
+
+ PluginSet::const_iterator end = newPlugins.end();
+ for (PluginSet::const_iterator it = newPlugins.begin(); it != end; ++it)
+ pluginsToUnload.remove(*it);
+
+ end = m_plugins.end();
+ for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it)
+ newPlugins.remove(*it);
+
+ // Unload plugins
+ end = pluginsToUnload.end();
+ for (PluginSet::const_iterator it = pluginsToUnload.begin(); it != end; ++it)
+ m_plugins.remove(*it);
+
+ // Add new plugins
+ end = newPlugins.end();
+ for (PluginSet::const_iterator it = newPlugins.begin(); it != end; ++it)
+ m_plugins.add(*it);
+
+ pluginSetChanged = !pluginsToUnload.isEmpty() || !newPlugins.isEmpty();
+ } else {
+ m_plugins = newPlugins;
+ PluginSet::const_iterator end = newPlugins.end();
+ for (PluginSet::const_iterator it = newPlugins.begin(); it != end; ++it)
+ m_plugins.add(*it);
+
+ pluginSetChanged = !newPlugins.isEmpty();
+ }
+
+ // Register plug-in MIME types
+ 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_end = (*it)->mimeToDescriptions().end();
+ for (MIMEToDescriptionsMap::const_iterator map_it = (*it)->mimeToDescriptions().begin(); map_it != map_end; ++map_it) {
+ m_registeredMIMETypes.add(map_it->first);
+ }
+ }
+
+ return pluginSetChanged;
+}
+
+Vector<PluginPackage*> PluginDatabase::plugins() const
+{
+ Vector<PluginPackage*> result;
+
+ PluginSet::const_iterator end = m_plugins.end();
+ for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it)
+ result.append((*it).get());
+
+ return result;
+}
+
static inline void addPluginsFromRegistry(HKEY rootKey, PluginSet& plugins)
{
HKEY key;
@@ -351,14 +435,106 @@ Vector<String> PluginDatabase::defaultPluginPaths()
return paths;
}
-bool PluginDatabase::isPreferredPluginPath(const String& path)
+bool PluginDatabase::isMIMETypeRegistered(const String& mimeType)
+{
+ if (mimeType.isNull())
+ return false;
+ if (m_registeredMIMETypes.contains(mimeType))
+ return true;
+ // No plugin was found, try refreshing the database and searching again
+ return (refresh() && m_registeredMIMETypes.contains(mimeType));
+}
+
+PluginPackage* PluginDatabase::pluginForMIMEType(const String& mimeType)
{
+ if (mimeType.isEmpty())
+ return 0;
+
+ String key = mimeType.lower();
String ourPath = safariPluginsPath();
+ PluginPackage* plugin = 0;
+ PluginSet::const_iterator end = m_plugins.end();
+
+ for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) {
+ if ((*it)->mimeToDescriptions().contains(key)) {
+ plugin = (*it).get();
+ // prefer plugins in our own plugins directory
+ if (plugin->parentDirectory() == ourPath)
+ break;
+ }
+ }
- if (!ourPath.isNull() && !path.isNull())
- return ourPath == path;
+ return plugin;
+}
- return false;
+String PluginDatabase::MIMETypeForExtension(const String& extension) const
+{
+ if (extension.isEmpty())
+ return String();
+
+ PluginSet::const_iterator end = m_plugins.end();
+ String ourPath = safariPluginsPath();
+ String mimeType;
+ PluginPackage* plugin = 0;
+
+ for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) {
+ MIMEToExtensionsMap::const_iterator mime_end = (*it)->mimeToExtensions().end();
+
+ for (MIMEToExtensionsMap::const_iterator mime_it = (*it)->mimeToExtensions().begin(); mime_it != mime_end; ++mime_it) {
+ const Vector<String>& extensions = mime_it->second;
+ for (unsigned i = 0; i < extensions.size(); i++) {
+ if (equalIgnoringCase(extensions[i], extension)) {
+ mimeType = mime_it->first;
+ plugin = (*it).get();
+ // prefer plugins in our own plugins directory
+ if (plugin->parentDirectory() == ourPath)
+ break;
+ }
+ }
+ }
+ }
+
+ return mimeType;
+}
+
+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("/")) {
+ int extensionPos = filename.reverseFind('.');
+ if (extensionPos != -1) {
+ String extension = filename.substring(extensionPos + 1);
+
+ mimeType = MIMETypeForExtension(extension);
+ plugin = pluginForMIMEType(mimeType);
+ }
+ }
+ }
+
+ // FIXME: if no plugin could be found, query Windows for the mime type
+ // corresponding to the extension.
+
+ return plugin;
+}
+
+PluginView* PluginDatabase::createPluginView(Frame* parentFrame, const IntSize& size, Element* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
+{
+ // if we fail to find a plugin for this MIME type, findPlugin will search for
+ // a plugin by the file extension and update the MIME type, so pass a mutable String
+ String mimeTypeCopy = mimeType;
+ PluginPackage* plugin = findPlugin(url, mimeTypeCopy);
+
+ // No plugin was found, try refreshing the database and searching again
+ if (!plugin && refresh()) {
+ mimeTypeCopy = mimeType;
+ plugin = findPlugin(url, mimeTypeCopy);
+ }
+
+ return new PluginView(parentFrame, size, plugin, element, url, paramNames, paramValues, mimeTypeCopy, loadManually);
}
}
diff --git a/WebCore/plugins/win/PluginPackageWin.cpp b/WebCore/plugins/win/PluginPackageWin.cpp
index ccc7586..c744822 100644
--- a/WebCore/plugins/win/PluginPackageWin.cpp
+++ b/WebCore/plugins/win/PluginPackageWin.cpp
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,76 +28,124 @@
#include "config.h"
#include "PluginPackage.h"
-#include "CString.h"
-#include "MIMETypeRegistry.h"
-#include "PluginDatabase.h"
-#include "PluginDebug.h"
#include "Timer.h"
+#include "DeprecatedString.h"
#include "npruntime_impl.h"
-#include <string.h>
-#include <wtf/OwnArrayPtr.h>
+#include "PluginDebug.h"
namespace WebCore {
+PluginPackage::~PluginPackage()
+{
+ ASSERT(!m_isLoaded);
+}
+
static String getVersionInfo(const LPVOID versionInfoData, const String& info)
{
LPVOID buffer;
UINT bufferLength;
String subInfo = "\\StringfileInfo\\040904E4\\" + info;
- bool retval = VerQueryValueW(versionInfoData,
- const_cast<UChar*>(subInfo.charactersWithNullTermination()),
- &buffer, &bufferLength);
+
+ bool retval = VerQueryValueW(versionInfoData, const_cast<UChar*>(subInfo.charactersWithNullTermination()),
+ &buffer, &bufferLength);
if (!retval || bufferLength == 0)
return String();
- // Subtract 1 from the length; we don't want the trailing null character.
+ // Subtract 1 from the length; we don't want the trailing 0
return String(reinterpret_cast<UChar*>(buffer), bufferLength - 1);
}
-int PluginPackage::compareFileVersion(const PlatformModuleVersion& compareVersion) const
+static Vector<String> splitString(const String& str, char delimiter, int padTo)
+{
+ int pos = 0;
+ int newPos;
+ Vector<String> result;
+ DeprecatedString ds = str.deprecatedString();
+ String s;
+ do {
+
+ newPos = ds.find(delimiter, pos);
+
+ if (newPos == -1)
+ s = ds.mid(pos);
+ else
+ s = ds.mid(pos, newPos - pos);
+
+ if (!s.isEmpty())
+ result.append(s);
+
+ pos = newPos + 1;
+ } while (newPos != -1);
+
+ while (padTo != -1 && static_cast<int>(result.size()) < padTo)
+ result.append("");
+
+ return result;
+}
+
+void PluginPackage::freeLibrarySoon()
+{
+ ASSERT(!m_freeLibraryTimer.isActive());
+ ASSERT(m_module);
+ ASSERT(m_loadCount == 0);
+
+ m_freeLibraryTimer.startOneShot(0);
+}
+
+void PluginPackage::freeLibraryTimerFired(Timer<PluginPackage>* /*timer*/)
+{
+ ASSERT(m_module);
+ ASSERT(m_loadCount == 0);
+
+ ::FreeLibrary(m_module);
+ m_module = 0;
+}
+
+PluginPackage::PluginPackage(const String& path, const FILETIME& lastModified)
+ : m_path(path)
+ , m_module(0)
+ , m_lastModified(lastModified)
+ , m_isLoaded(false)
+ , m_loadCount(0)
+ , m_freeLibraryTimer(this, &PluginPackage::freeLibraryTimerFired)
+ , m_fileVersionLS(0)
+ , m_fileVersionMS(0)
+{
+ m_fileName = String(PathFindFileName(m_path.charactersWithNullTermination()));
+ m_parentDirectory = m_path.left(m_path.length() - m_fileName.length() - 1);
+}
+
+int PluginPackage::compareFileVersion(unsigned compareVersionMS, unsigned compareVersionLS) 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;
+ if (m_fileVersionMS != compareVersionMS)
+ return m_fileVersionMS > compareVersionMS ? 1 : -1;
+ if (m_fileVersionLS != compareVersionLS)
+ return m_fileVersionLS > compareVersionLS ? 1 : -1;
return 0;
}
-int PluginPackage::compare(const PluginPackage& compareTo) const
+void PluginPackage::storeFileVersion(LPVOID versionInfoData)
{
- // Sort plug-ins that allow multiple instances first.
- bool AallowsMultipleInstances = !quirks().contains(PluginQuirkDontAllowMultipleInstances);
- bool BallowsMultipleInstances = !compareTo.quirks().contains(PluginQuirkDontAllowMultipleInstances);
- if (AallowsMultipleInstances != BallowsMultipleInstances)
- return AallowsMultipleInstances ? -1 : 1;
-
- // Sort plug-ins in a preferred path first.
- bool AisInPreferredPath = PluginDatabase::isPreferredPluginPath(parentDirectory());
- bool BisInPreferredPath = PluginDatabase::isPreferredPluginPath(compareTo.parentDirectory());
- if (AisInPreferredPath != BisInPreferredPath)
- return AisInPreferredPath ? -1 : 1;
-
- int diff = strcmp(name().utf8().data(), compareTo.name().utf8().data());
- if (diff)
- return diff;
-
- if (diff = compareFileVersion(compareTo.version()))
- return diff;
-
- return strcmp(parentDirectory().utf8().data(), compareTo.parentDirectory().utf8().data());
+ VS_FIXEDFILEINFO* info;
+ UINT infoSize;
+ if (!VerQueryValue(versionInfoData, TEXT("\\"), (LPVOID*) &info, &infoSize) || infoSize < sizeof(VS_FIXEDFILEINFO))
+ return;
+ m_fileVersionLS = info->dwFileVersionLS;
+ m_fileVersionMS = info->dwFileVersionMS;
}
bool PluginPackage::isPluginBlacklisted()
{
- static const PlatformModuleVersion slPluginMinRequired(0x51BE0000, 0x00010000);
+ static const unsigned silverlightPluginMinRequiredVersionMS = 0x00010000;
+ static const unsigned silverlightPluginMinRequiredVersionLS = 0x51BE0000;
if (name() == "Silverlight Plug-In") {
// workaround for <rdar://5557379> Crash in Silverlight when opening microsoft.com.
// the latest 1.0 version of Silverlight does not reproduce this crash, so allow it
// and any newer versions
- if (compareFileVersion(slPluginMinRequired) < 0)
+ if (compareFileVersion(silverlightPluginMinRequiredVersionMS, silverlightPluginMinRequiredVersionLS) < 0)
return true;
} else if (fileName() == "npmozax.dll")
// Bug 15217: Mozilla ActiveX control complains about missing xpcom_core.dll
@@ -107,134 +154,58 @@ bool PluginPackage::isPluginBlacklisted()
return false;
}
-void PluginPackage::determineQuirks(const String& mimeType)
-{
- static const PlatformModuleVersion lastKnownUnloadableRealPlayerVersion(0x000B0B24, 0x00060000);
-
- if (mimeType == "application/x-shockwave-flash") {
- // The flash plugin only requests windowless plugins if we return a mozilla user agent
- m_quirks.add(PluginQuirkWantsMozillaUserAgent);
- m_quirks.add(PluginQuirkThrottleInvalidate);
- m_quirks.add(PluginQuirkThrottleWMUserPlusOneMessages);
- m_quirks.add(PluginQuirkFlashURLNotifyBug);
- }
-
- if (name().contains("Microsoft") && name().contains("Windows Media")) {
- // The WMP plugin sets its size on the first NPP_SetWindow call and never updates its size, so
- // call SetWindow when the plugin view has a correct size
- m_quirks.add(PluginQuirkDeferFirstSetWindowCall);
-
- // Windowless mode does not work at all with the WMP plugin so just remove that parameter
- // and don't pass it to the plug-in.
- m_quirks.add(PluginQuirkRemoveWindowlessVideoParam);
-
- // WMP has a modal message loop that it enters whenever we call it or
- // ask it to paint. This modal loop can deliver messages to other
- // windows in WebKit at times when they are not expecting them (for
- // example, delivering a WM_PAINT message during a layout), and these
- // can cause crashes.
- m_quirks.add(PluginQuirkHasModalMessageLoop);
- }
-
- if (name() == "VLC Multimedia Plugin") {
- // VLC hangs on NPP_Destroy if we call NPP_SetWindow with a null window handle
- m_quirks.add(PluginQuirkDontSetNullWindowHandleOnDestroy);
-
- // VLC 0.8.6d and 0.8.6e crash if multiple instances are created.
- // <rdar://problem/5773070> tracks allowing multiple instances when this
- // bug is fixed.
- m_quirks.add(PluginQuirkDontAllowMultipleInstances);
- }
-
- // The DivX plugin sets its size on the first NPP_SetWindow call and never updates its size, so
- // call SetWindow when the plugin view has a correct size
- if (mimeType == "video/divx")
- m_quirks.add(PluginQuirkDeferFirstSetWindowCall);
-
- // FIXME: This is a workaround for a problem in our NPRuntime bindings; if a plug-in creates an
- // NPObject and passes it to a function it's not possible to see what root object that NPObject belongs to.
- // Thus, we don't know that the object should be invalidated when the plug-in instance goes away.
- // See <rdar://problem/5487742>.
- if (mimeType == "application/x-silverlight")
- m_quirks.add(PluginQuirkDontUnloadPlugin);
-
- if (MIMETypeRegistry::isJavaAppletMIMEType(mimeType)) {
- // Because a single process cannot create multiple VMs, and we cannot reliably unload a
- // Java VM, we cannot unload the Java plugin, or we'll lose reference to our only VM
- m_quirks.add(PluginQuirkDontUnloadPlugin);
-
- // Setting the window region to an empty region causes bad scrolling repaint problems
- // with the Java plug-in.
- m_quirks.add(PluginQuirkDontClipToZeroRectWhenScrolling);
- }
-
- if (mimeType == "audio/x-pn-realaudio-plugin") {
- // Prevent the Real plugin from calling the Window Proc recursively, causing the stack to overflow.
- m_quirks.add(PluginQuirkDontCallWndProcForSameMessageRecursively);
-
- // Unloading RealPlayer versions newer than 10.5 can cause a hang; see rdar://5669317.
- // FIXME: Resume unloading when this bug in the RealPlayer Plug-In is fixed (rdar://5713147)
- if (compareFileVersion(lastKnownUnloadableRealPlayerVersion) > 0)
- m_quirks.add(PluginQuirkDontUnloadPlugin);
- }
-}
-
bool PluginPackage::fetchInfo()
{
DWORD versionInfoSize, zeroHandle;
versionInfoSize = GetFileVersionInfoSizeW(m_path.charactersWithNullTermination(), &zeroHandle);
+
if (versionInfoSize == 0)
return false;
- OwnArrayPtr<char> versionInfoData(new char[versionInfoSize]);
+ LPVOID versionInfoData = fastMalloc(versionInfoSize);
- if (!GetFileVersionInfoW(m_path.charactersWithNullTermination(), 0, versionInfoSize, versionInfoData.get()))
+ if (!GetFileVersionInfoW(m_path.charactersWithNullTermination(), 0, versionInfoSize, versionInfoData)) {
+ fastFree(versionInfoData);
return false;
+ }
- m_name = getVersionInfo(versionInfoData.get(), "ProductName");
- m_description = getVersionInfo(versionInfoData.get(), "FileDescription");
- if (m_name.isNull() || m_description.isNull())
- return false;
+ m_name = getVersionInfo(versionInfoData, "ProductName");
+ m_description = getVersionInfo(versionInfoData, "FileDescription");
- VS_FIXEDFILEINFO* info;
- UINT infoSize;
- if (!VerQueryValue(versionInfoData.get(), TEXT("\\"), (LPVOID*) &info, &infoSize) || infoSize < sizeof(VS_FIXEDFILEINFO))
+ if (m_name.isNull() || m_description.isNull()) {
+ fastFree(versionInfoData);
return false;
- m_moduleVersion.leastSig = info->dwFileVersionLS;
- m_moduleVersion.mostSig = info->dwFileVersionMS;
+ }
- if (isPluginBlacklisted())
- return false;
+ storeFileVersion(versionInfoData);
- Vector<String> types;
- getVersionInfo(versionInfoData.get(), "MIMEType").split('|', types);
- Vector<String> extensionLists;
- getVersionInfo(versionInfoData.get(), "FileExtents").split('|', extensionLists);
- Vector<String> descriptions;
- getVersionInfo(versionInfoData.get(), "FileOpenName").split('|', descriptions);
+ if (isPluginBlacklisted()) {
+ fastFree(versionInfoData);
+ return false;
+ }
- for (unsigned i = 0; i < types.size(); i++) {
- String type = types[i].lower();
- String description = i < descriptions.size() ? descriptions[i] : "";
- String extensionList = i < extensionLists.size() ? extensionLists[i] : "";
+ Vector<String> mimeTypes = splitString(getVersionInfo(versionInfoData, "MIMEType"), '|', -1);
+ Vector<String> fileExtents = splitString(getVersionInfo(versionInfoData, "FileExtents"), '|', mimeTypes.size());
+ Vector<String> descriptions = splitString(getVersionInfo(versionInfoData, "FileOpenName"), '|', mimeTypes.size());
- Vector<String> extensionsVector;
- extensionList.split(',', extensionsVector);
+ fastFree(versionInfoData);
- // Get rid of the extension list that may be at the end of the description string.
+ for (unsigned i = 0; i < mimeTypes.size(); i++) {
+ // Get rid of the extension list in the description string
+ String description = descriptions[i];
int pos = description.find("(*");
if (pos != -1) {
- // There might be a space that we need to get rid of.
+ // There might be a space that we need to get rid of
if (pos > 1 && description[pos - 1] == ' ')
pos--;
+
description = description.left(pos);
}
- // Determine the quirks for the MIME types this plug-in supports
- determineQuirks(type);
+ mimeTypes[i] = mimeTypes[i].lower();
- m_mimeToExtensions.add(type, extensionsVector);
- m_mimeToDescriptions.add(type, description);
+ m_mimeToExtensions.add(mimeTypes[i], splitString(fileExtents[i], ',', -1));
+ m_mimeToDescriptions.add(mimeTypes[i], description);
}
return true;
@@ -246,8 +217,6 @@ bool PluginPackage::load()
ASSERT(m_module);
m_freeLibraryTimer.stop();
} else if (m_isLoaded) {
- if (m_quirks.contains(PluginQuirkDontAllowMultipleInstances))
- return false;
m_loadCount++;
return true;
} else {
@@ -298,7 +267,6 @@ bool PluginPackage::load()
memset(&m_browserFuncs, 0, sizeof(m_browserFuncs));
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;
@@ -352,21 +320,64 @@ bool PluginPackage::load()
m_loadCount++;
return true;
-
abort:
unloadWithoutShutdown();
return false;
}
+void PluginPackage::unload()
+{
+ if (!m_isLoaded)
+ return;
+
+ if (--m_loadCount > 0)
+ return;
+
+ m_NPP_Shutdown();
+
+ unloadWithoutShutdown();
+}
+
+void PluginPackage::unloadWithoutShutdown()
+{
+ if (!m_isLoaded)
+ return;
+
+ ASSERT(m_loadCount == 0);
+ ASSERT(m_module);
+
+ // <rdar://5530519>: Crash when closing tab with pdf file (Reader 7 only)
+ // If the plugin has subclassed its parent window, as with Reader 7, we may have
+ // gotten here by way of the plugin's internal window proc forwarding a message to our
+ // original window proc. If we free the plugin library from here, we will jump back
+ // to code we just freed when we return, so delay calling FreeLibrary at least until
+ // the next message loop
+ freeLibrarySoon();
+
+ m_isLoaded = false;
+}
+
+PluginPackage* PluginPackage::createPackage(const String& path, const FILETIME& lastModified)
+{
+ PluginPackage* package = new PluginPackage(path, lastModified);
+
+ if (!package->fetchInfo()) {
+ delete package;
+ return 0;
+ }
+
+ return package;
+}
+
unsigned PluginPackage::hash() const
{
- const unsigned hashCodes[3] = {
+ unsigned hashCodes[3] = {
m_description.impl()->hash(),
m_lastModified.dwLowDateTime,
m_lastModified.dwHighDateTime
};
- return StringImpl::computeHash(reinterpret_cast<const UChar*>(hashCodes), 3 * sizeof(unsigned) / sizeof(UChar));
+ return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), 3 * sizeof(unsigned) / sizeof(UChar));
}
bool PluginPackage::equal(const PluginPackage& a, const PluginPackage& b)
diff --git a/WebCore/plugins/win/PluginViewWin.cpp b/WebCore/plugins/win/PluginViewWin.cpp
index 4275b2c..b219fa5 100644
--- a/WebCore/plugins/win/PluginViewWin.cpp
+++ b/WebCore/plugins/win/PluginViewWin.cpp
@@ -51,7 +51,6 @@
#include "kjs_binding.h"
#include "kjs_proxy.h"
#include "kjs_window.h"
-#include "PluginDatabase.h"
#include "PluginDebug.h"
#include "PluginPackage.h"
#include "npruntime_impl.h"
@@ -208,11 +207,11 @@ private:
static String scriptStringIfJavaScriptURL(const KURL& url)
{
- if (!url.protocolIs("javascript"))
+ if (!url.string().startsWith("javascript:", false))
return String();
// This returns an unescaped string
- return decodeURLEscapeSequences(url.string().substring(11));
+ return KURL::decode_string(url.deprecatedString().mid(11));
}
PluginView* PluginView::s_currentPluginView = 0;
@@ -300,12 +299,12 @@ PluginView::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
}
if (message == m_lastMessage &&
- m_plugin->quirks().contains(PluginQuirkDontCallWndProcForSameMessageRecursively) &&
+ m_quirks.contains(PluginQuirkDontCallWndProcForSameMessageRecursively) &&
m_isCallingPluginWndProc)
return 1;
if (message == WM_USER + 1 &&
- m_plugin->quirks().contains(PluginQuirkThrottleWMUserPlusOneMessages)) {
+ m_quirks.contains(PluginQuirkThrottleWMUserPlusOneMessages)) {
if (!m_messageThrottler)
m_messageThrottler.set(new PluginMessageThrottlerWin(this));
@@ -359,7 +358,7 @@ void PluginView::updateWindow() const
// To prevent flashes while scrolling, we disable drawing during the window
// update process by clipping the window to the zero rect.
- bool clipToZeroRect = !m_plugin->quirks().contains(PluginQuirkDontClipToZeroRectWhenScrolling);
+ bool clipToZeroRect = !m_quirks.contains(PluginQuirkDontClipToZeroRectWhenScrolling);
if (clipToZeroRect) {
rgn = ::CreateRectRgn(0, 0, 0, 0);
@@ -785,7 +784,7 @@ void PluginView::stop()
// Clear the window
m_npWindow.window = 0;
- if (m_plugin->pluginFuncs()->setwindow && !m_plugin->quirks().contains(PluginQuirkDontSetNullWindowHandleOnDestroy)) {
+ if (m_plugin->pluginFuncs()->setwindow && !m_quirks.contains(PluginQuirkDontSetNullWindowHandleOnDestroy)) {
setCallingPlugin(true);
m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow);
setCallingPlugin(false);
@@ -868,7 +867,7 @@ void PluginView::performRequest(PluginRequest* request)
// if this is not a targeted request, create a stream for it. otherwise,
// just pass it off to the loader
if (targetFrameName.isEmpty()) {
- PluginStream* stream = new PluginStream(this, m_parentFrame, request->frameLoadRequest().resourceRequest(), request->sendNotification(), request->notifyData(), plugin()->pluginFuncs(), instance(), m_plugin->quirks());
+ PluginStream* stream = new PluginStream(this, m_parentFrame, request->frameLoadRequest().resourceRequest(), request->sendNotification(), request->notifyData(), plugin()->pluginFuncs(), instance(), m_quirks);
m_streams.add(stream);
stream->start();
} else {
@@ -878,7 +877,7 @@ void PluginView::performRequest(PluginRequest* request)
if (request->sendNotification()) {
KJS::JSLock::DropAllLocks dropAllLocks;
setCallingPlugin(true);
- m_plugin->pluginFuncs()->urlnotify(m_instance, requestURL.string().utf8().data(), NPRES_DONE, request->notifyData());
+ m_plugin->pluginFuncs()->urlnotify(m_instance, requestURL.deprecatedString().utf8(), NPRES_DONE, request->notifyData());
setCallingPlugin(false);
}
}
@@ -900,7 +899,7 @@ void PluginView::performRequest(PluginRequest* request)
if (getString(parentFrame->scriptProxy(), result, resultString))
cstr = resultString.utf8();
- RefPtr<PluginStream> stream = new PluginStream(this, m_parentFrame, request->frameLoadRequest().resourceRequest(), request->sendNotification(), request->notifyData(), plugin()->pluginFuncs(), instance(), m_plugin->quirks());
+ RefPtr<PluginStream> stream = new PluginStream(this, m_parentFrame, request->frameLoadRequest().resourceRequest(), request->sendNotification(), request->notifyData(), plugin()->pluginFuncs(), instance(), m_quirks);
m_streams.add(stream);
stream->sendJavaScriptStream(requestURL, cstr);
}
@@ -962,9 +961,9 @@ NPError PluginView::load(const FrameLoadRequest& frameLoadRequest, bool sendNoti
static KURL makeURL(const KURL& baseURL, const char* relativeURLString)
{
- String urlString = relativeURLString;
+ DeprecatedString urlString = DeprecatedString::fromLatin1(relativeURLString);
- // Strip return characters.
+ // Strip return characters
urlString.replace('\n', "");
urlString.replace('\r', "");
@@ -1108,7 +1107,7 @@ static inline HTTPHeaderMap parseRFC822HeaderFields(const Vector<char>& buffer,
} else {
// Merge the continuation of the previous header
String currentValue = headerFields.get(lastKey);
- String newValue(line, lineLength);
+ String newValue = DeprecatedString::fromLatin1(line, lineLength);
headerFields.set(lastKey, currentValue + newValue);
}
@@ -1122,7 +1121,7 @@ static inline HTTPHeaderMap parseRFC822HeaderFields(const Vector<char>& buffer,
// malformed header; ignore it and continue
continue;
else {
- lastKey = capitalizeRFC822HeaderFieldName(String(line, colon - line));
+ lastKey = capitalizeRFC822HeaderFieldName(DeprecatedString::fromLatin1(line, colon - line));
String value;
for (colon++; colon != eol; colon++) {
@@ -1132,7 +1131,7 @@ static inline HTTPHeaderMap parseRFC822HeaderFields(const Vector<char>& buffer,
if (colon == eol)
value = "";
else
- value = String(colon, eol - colon);
+ value = DeprecatedString::fromLatin1(colon, eol - colon);
String oldValue = headerFields.get(lastKey);
if (!oldValue.isNull()) {
@@ -1161,7 +1160,7 @@ NPError PluginView::handlePost(const char* url, const char* target, uint32 len,
Vector<char> buffer;
if (file) {
- String filename(buf, len);
+ String filename = DeprecatedString::fromLatin1(buf, len);
if (filename.startsWith("file:///"))
filename = filename.substring(8);
@@ -1225,7 +1224,7 @@ NPError PluginView::handlePost(const char* url, const char* target, uint32 len,
frameLoadRequest.resourceRequest().setHTTPMethod("POST");
frameLoadRequest.resourceRequest().setURL(makeURL(m_baseURL, url));
frameLoadRequest.resourceRequest().addHTTPHeaderFields(headerFields);
- frameLoadRequest.resourceRequest().setHTTPBody(FormData::create(postData, postDataLength));
+ frameLoadRequest.resourceRequest().setHTTPBody(PassRefPtr<FormData>(new FormData(postData, postDataLength)));
frameLoadRequest.setFrameName(target);
return load(frameLoadRequest, sendNotification, notifyData);
@@ -1269,7 +1268,7 @@ NPError PluginView::destroyStream(NPStream* stream, NPReason reason)
const char* PluginView::userAgent()
{
- if (m_plugin->quirks().contains(PluginQuirkWantsMozillaUserAgent))
+ if (m_quirks.contains(PluginQuirkWantsMozillaUserAgent))
return MozillaUserAgent;
if (m_userAgent.isNull())
@@ -1279,8 +1278,10 @@ const char* PluginView::userAgent()
void PluginView::status(const char* message)
{
+ String s = DeprecatedString::fromLatin1(message);
+
if (Page* page = m_parentFrame->page())
- page->chrome()->setStatusbarText(m_parentFrame, String(message));
+ page->chrome()->setStatusbarText(m_parentFrame, s);
}
NPError PluginView::getValue(NPNVariable variable, void* value)
@@ -1365,7 +1366,7 @@ void PluginView::invalidateRect(NPRect* rect)
RECT invalidRect(r);
InvalidateRect(m_window, &invalidRect, FALSE);
} else {
- if (m_plugin->quirks().contains(PluginQuirkThrottleInvalidate)) {
+ if (m_quirks.contains(PluginQuirkThrottleInvalidate)) {
m_invalidRects.append(r);
if (!m_invalidateTimer.isActive())
m_invalidateTimer.startOneShot(0.001);
@@ -1455,7 +1456,7 @@ PluginView::~PluginView()
m_parentFrame->cleanupScriptObjectsForPlugin(this);
- if (m_plugin && !m_plugin->quirks().contains(PluginQuirkDontUnloadPlugin))
+ if (m_plugin && !m_quirks.contains(PluginQuirkDontUnloadPlugin))
m_plugin->unload();
}
@@ -1466,6 +1467,73 @@ void PluginView::disconnectStream(PluginStream* stream)
m_streams.remove(stream);
}
+void PluginView::determineQuirks(const String& mimeType)
+{
+ static const unsigned lastKnownUnloadableRealPlayerVersionLS = 0x000B0B24;
+ static const unsigned lastKnownUnloadableRealPlayerVersionMS = 0x00060000;
+
+ if (mimeType == "application/x-shockwave-flash") {
+ // The flash plugin only requests windowless plugins if we return a mozilla user agent
+ m_quirks.add(PluginQuirkWantsMozillaUserAgent);
+ m_quirks.add(PluginQuirkThrottleInvalidate);
+ m_quirks.add(PluginQuirkThrottleWMUserPlusOneMessages);
+ m_quirks.add(PluginQuirkFlashURLNotifyBug);
+ }
+
+ if (m_plugin->name().contains("Microsoft") && m_plugin->name().contains("Windows Media")) {
+ // The WMP plugin sets its size on the first NPP_SetWindow call and never updates its size, so
+ // call SetWindow when the plugin view has a correct size
+ m_quirks.add(PluginQuirkDeferFirstSetWindowCall);
+
+ // Windowless mode does not work at all with the WMP plugin so just remove that parameter
+ // and don't pass it to the plug-in.
+ m_quirks.add(PluginQuirkRemoveWindowlessVideoParam);
+
+ // WMP has a modal message loop that it enters whenever we call it or
+ // ask it to paint. This modal loop can deliver messages to other
+ // windows in WebKit at times when they are not expecting them (for
+ // example, delivering a WM_PAINT message during a layout), and these
+ // can cause crashes.
+ m_quirks.add(PluginQuirkHasModalMessageLoop);
+ }
+
+ // VLC hangs on NPP_Destroy if we call NPP_SetWindow with a null window handle
+ if (m_plugin->name() == "VLC Multimedia Plugin")
+ m_quirks.add(PluginQuirkDontSetNullWindowHandleOnDestroy);
+
+ // The DivX plugin sets its size on the first NPP_SetWindow call and never updates its size, so
+ // call SetWindow when the plugin view has a correct size
+ if (mimeType == "video/divx")
+ m_quirks.add(PluginQuirkDeferFirstSetWindowCall);
+
+ // FIXME: This is a workaround for a problem in our NPRuntime bindings; if a plug-in creates an
+ // NPObject and passes it to a function it's not possible to see what root object that NPObject belongs to.
+ // Thus, we don't know that the object should be invalidated when the plug-in instance goes away.
+ // See <rdar://problem/5487742>.
+ if (mimeType == "application/x-silverlight")
+ m_quirks.add(PluginQuirkDontUnloadPlugin);
+
+ if (MIMETypeRegistry::isJavaAppletMIMEType(mimeType)) {
+ // Because a single process cannot create multiple VMs, and we cannot reliably unload a
+ // Java VM, we cannot unload the Java plugin, or we'll lose reference to our only VM
+ m_quirks.add(PluginQuirkDontUnloadPlugin);
+
+ // Setting the window region to an empty region causes bad scrolling repaint problems
+ // with the Java plug-in.
+ m_quirks.add(PluginQuirkDontClipToZeroRectWhenScrolling);
+ }
+
+ if (mimeType == "audio/x-pn-realaudio-plugin") {
+ // Prevent the Real plugin from calling the Window Proc recursively, causing the stack to overflow.
+ m_quirks.add(PluginQuirkDontCallWndProcForSameMessageRecursively);
+
+ // Unloading RealPlayer versions newer than 10.5 can cause a hang; see rdar://5669317.
+ // FIXME: Resume unloading when this bug in the RealPlayer Plug-In is fixed (rdar://5713147)
+ if (m_plugin->compareFileVersion(lastKnownUnloadableRealPlayerVersionMS, lastKnownUnloadableRealPlayerVersionLS) > 0)
+ m_quirks.add(PluginQuirkDontUnloadPlugin);
+ }
+}
+
void PluginView::setParameters(const Vector<String>& paramNames, const Vector<String>& paramValues)
{
ASSERT(paramNames.size() == paramValues.size());
@@ -1477,7 +1545,7 @@ void PluginView::setParameters(const Vector<String>& paramNames, const Vector<St
m_paramValues = reinterpret_cast<char**>(fastMalloc(sizeof(char*) * size));
for (unsigned i = 0; i < size; i++) {
- if (m_plugin->quirks().contains(PluginQuirkRemoveWindowlessVideoParam) && equalIgnoringCase(paramNames[i], "windowlessvideo"))
+ if (m_quirks.contains(PluginQuirkRemoveWindowlessVideoParam) && equalIgnoringCase(paramNames[i], "windowlessvideo"))
continue;
m_paramNames[paramCount] = createUTF8String(paramNames[i]);
@@ -1495,7 +1563,7 @@ PluginView::PluginView(Frame* parentFrame, const IntSize& size, PluginPackage* p
, m_element(element)
, m_isStarted(false)
, m_url(url)
- , m_baseURL(m_parentFrame->loader()->completeURL(m_parentFrame->document()->baseURL().string()))
+ , m_baseURL(m_parentFrame->loader()->completeURL(m_parentFrame->document()->baseURL()))
, m_status(PluginStatusLoadedSuccessfully)
, m_requestTimer(this, &PluginView::requestTimerFired)
, m_invalidateTimer(this, &PluginView::invalidateTimerFired)
@@ -1523,6 +1591,7 @@ PluginView::PluginView(Frame* parentFrame, const IntSize& size, PluginPackage* p
m_instance->ndata = this;
m_mimeType = mimeType.utf8();
+ determineQuirks(mimeType);
setParameters(paramNames, paramValues);
@@ -1576,7 +1645,7 @@ void PluginView::init()
m_npWindow.window = 0;
}
- if (!m_plugin->quirks().contains(PluginQuirkDeferFirstSetWindowCall))
+ if (!m_quirks.contains(PluginQuirkDeferFirstSetWindowCall))
setNPWindowRect(frameGeometry());
m_status = PluginStatusLoadedSuccessfully;
@@ -1587,7 +1656,7 @@ void PluginView::didReceiveResponse(const ResourceResponse& response)
ASSERT(m_loadManually);
ASSERT(!m_manualStream);
- m_manualStream = new PluginStream(this, m_parentFrame, m_parentFrame->loader()->activeDocumentLoader()->request(), false, 0, plugin()->pluginFuncs(), instance(), m_plugin->quirks());
+ m_manualStream = new PluginStream(this, m_parentFrame, m_parentFrame->loader()->activeDocumentLoader()->request(), false, 0, plugin()->pluginFuncs(), instance(), m_quirks);
m_manualStream->setLoadManually(true);
m_manualStream->didReceiveResponse(0, response);
@@ -1619,7 +1688,7 @@ void PluginView::didFail(const ResourceError& error)
void PluginView::setCallingPlugin(bool b) const
{
- if (!m_plugin->quirks().contains(PluginQuirkHasModalMessageLoop))
+ if (!m_quirks.contains(PluginQuirkHasModalMessageLoop))
return;
if (b)
@@ -1635,20 +1704,4 @@ bool PluginView::isCallingPlugin()
return s_callingPlugin > 0;
}
-PluginView* PluginView::create(Frame* parentFrame, const IntSize& size, Element* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
-{
- // if we fail to find a plugin for this MIME type, findPlugin will search for
- // a plugin by the file extension and update the MIME type, so pass a mutable String
- String mimeTypeCopy = mimeType;
- PluginPackage* plugin = PluginDatabase::installedPlugins()->findPlugin(url, mimeTypeCopy);
-
- // No plugin was found, try refreshing the database and searching again
- if (!plugin && PluginDatabase::installedPlugins()->refresh()) {
- mimeTypeCopy = mimeType;
- plugin = PluginDatabase::installedPlugins()->findPlugin(url, mimeTypeCopy);
- }
-
- return new PluginView(parentFrame, size, plugin, element, url, paramNames, paramValues, mimeTypeCopy, loadManually);
-}
-
} // namespace WebCore