summaryrefslogtreecommitdiff
path: root/Source/WebKit2/UIProcess/Plugins
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/UIProcess/Plugins')
-rw-r--r--Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp226
-rw-r--r--Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h91
-rw-r--r--Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp108
-rw-r--r--Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h74
-rw-r--r--Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp264
-rw-r--r--Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h164
-rw-r--r--Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in37
-rw-r--r--Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp299
-rw-r--r--Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.h88
-rw-r--r--Source/WebKit2/UIProcess/Plugins/gtk/PluginProcessProxyGtk.cpp43
-rw-r--r--Source/WebKit2/UIProcess/Plugins/mac/PluginInfoStoreMac.mm102
-rw-r--r--Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm245
-rw-r--r--Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp43
-rw-r--r--Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp107
-rw-r--r--Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp408
15 files changed, 2299 insertions, 0 deletions
diff --git a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp
new file mode 100644
index 000000000..f37099f2c
--- /dev/null
+++ b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2010 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 INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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 "PluginModuleInfo.h"
+#include <WebCore/KURL.h>
+#include <WebCore/MIMETypeRegistry.h>
+#include <algorithm>
+#include <wtf/ListHashSet.h>
+#include <wtf/StdLibExtras.h>
+
+using namespace std;
+using namespace WebCore;
+
+namespace WebKit {
+
+PluginInfoStore::PluginInfoStore()
+ : m_pluginListIsUpToDate(false)
+{
+}
+
+void PluginInfoStore::setAdditionalPluginsDirectories(const Vector<String>& directories)
+{
+ m_additionalPluginsDirectories = directories;
+ refresh();
+}
+
+void PluginInfoStore::refresh()
+{
+ m_pluginListIsUpToDate = false;
+}
+
+template <typename T, typename U>
+static void addFromVector(T& hashSet, const U& vector)
+{
+ for (size_t i = 0; i < vector.size(); ++i)
+ hashSet.add(vector[i]);
+}
+
+// We use a ListHashSet so that plugins will be loaded from the additional plugins directories first
+// (which in turn means those plugins will be preferred if two plugins claim the same MIME type).
+#if OS(WINDOWS)
+typedef ListHashSet<String, 32, CaseFoldingHash> PathHashSet;
+#else
+typedef ListHashSet<String, 32> PathHashSet;
+#endif
+
+void PluginInfoStore::loadPluginsIfNecessary()
+{
+ if (m_pluginListIsUpToDate)
+ return;
+
+ PathHashSet uniquePluginPaths;
+
+ // First, load plug-ins from the additional plug-ins directories specified.
+ for (size_t i = 0; i < m_additionalPluginsDirectories.size(); ++i)
+ addFromVector(uniquePluginPaths, pluginPathsInDirectory(m_additionalPluginsDirectories[i]));
+
+ // Then load plug-ins from the standard plug-ins directories.
+ Vector<String> directories = pluginsDirectories();
+ for (size_t i = 0; i < directories.size(); ++i)
+ addFromVector(uniquePluginPaths, pluginPathsInDirectory(directories[i]));
+
+ // Then load plug-ins that are not in the standard plug-ins directories.
+ addFromVector(uniquePluginPaths, individualPluginPaths());
+
+ Vector<PluginModuleInfo> plugins;
+
+ PathHashSet::const_iterator end = uniquePluginPaths.end();
+ for (PathHashSet::const_iterator it = uniquePluginPaths.begin(); it != end; ++it)
+ loadPlugin(plugins, *it);
+
+ m_plugins.swap(plugins);
+ m_pluginListIsUpToDate = true;
+}
+
+void PluginInfoStore::loadPlugin(Vector<PluginModuleInfo>& plugins, const String& pluginPath)
+{
+ PluginModuleInfo plugin;
+
+ if (!getPluginInfo(pluginPath, plugin))
+ return;
+
+ if (!shouldUsePlugin(plugins, plugin))
+ return;
+
+ plugins.append(plugin);
+}
+
+Vector<PluginModuleInfo> PluginInfoStore::plugins()
+{
+ loadPluginsIfNecessary();
+
+ Vector<PluginModuleInfo> plugins(m_plugins);
+
+ return plugins;
+}
+
+PluginModuleInfo PluginInfoStore::findPluginForMIMEType(const String& mimeType) const
+{
+ ASSERT(!mimeType.isNull());
+
+ for (size_t i = 0; i < m_plugins.size(); ++i) {
+ const PluginModuleInfo& plugin = m_plugins[i];
+
+ for (size_t j = 0; j < plugin.info.mimes.size(); ++j) {
+ const MimeClassInfo& mimeClassInfo = plugin.info.mimes[j];
+ if (mimeClassInfo.type == mimeType)
+ return plugin;
+ }
+ }
+
+ return PluginModuleInfo();
+}
+
+PluginModuleInfo PluginInfoStore::findPluginForExtension(const String& extension, String& mimeType) const
+{
+ ASSERT(!extension.isNull());
+
+ for (size_t i = 0; i < m_plugins.size(); ++i) {
+ const PluginModuleInfo& plugin = m_plugins[i];
+
+ for (size_t j = 0; j < plugin.info.mimes.size(); ++j) {
+ const MimeClassInfo& mimeClassInfo = plugin.info.mimes[j];
+
+ const Vector<String>& extensions = mimeClassInfo.extensions;
+
+ if (find(extensions.begin(), extensions.end(), extension) != extensions.end()) {
+ // We found a supported extension, set the correct MIME type.
+ mimeType = mimeClassInfo.type;
+ return plugin;
+ }
+ }
+ }
+
+ return PluginModuleInfo();
+}
+
+static inline String pathExtension(const KURL& url)
+{
+ String extension;
+ String filename = url.lastPathComponent();
+ if (!filename.endsWith("/")) {
+ int extensionPos = filename.reverseFind('.');
+ if (extensionPos != -1)
+ extension = filename.substring(extensionPos + 1);
+ }
+
+ return extension;
+}
+
+#if !PLATFORM(MAC)
+String PluginInfoStore::getMIMETypeForExtension(const String& extension)
+{
+ return MIMETypeRegistry::getMIMETypeForExtension(extension);
+}
+#endif
+
+PluginModuleInfo PluginInfoStore::findPlugin(String& mimeType, const KURL& url)
+{
+ loadPluginsIfNecessary();
+
+ // First, check if we can get the plug-in based on its MIME type.
+ if (!mimeType.isNull()) {
+ PluginModuleInfo plugin = findPluginForMIMEType(mimeType);
+ if (!plugin.path.isNull())
+ return plugin;
+ }
+
+ // Next, check if any plug-ins claim to support the URL extension.
+ String extension = pathExtension(url).lower();
+ if (!extension.isNull() && mimeType.isEmpty()) {
+ PluginModuleInfo plugin = findPluginForExtension(extension, mimeType);
+ if (!plugin.path.isNull())
+ return plugin;
+
+ // Finally, try to get the MIME type from the extension in a platform specific manner and use that.
+ String extensionMimeType = getMIMETypeForExtension(extension);
+ if (!extensionMimeType.isNull()) {
+ PluginModuleInfo plugin = findPluginForMIMEType(extensionMimeType);
+ if (!plugin.path.isNull()) {
+ mimeType = extensionMimeType;
+ return plugin;
+ }
+ }
+ }
+
+ return PluginModuleInfo();
+}
+
+PluginModuleInfo PluginInfoStore::infoForPluginWithPath(const String& pluginPath) const
+{
+ for (size_t i = 0; i < m_plugins.size(); ++i) {
+ if (m_plugins[i].path == pluginPath)
+ return m_plugins[i];
+ }
+
+ ASSERT_NOT_REACHED();
+ return PluginModuleInfo();
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h
new file mode 100644
index 000000000..4bfecb424
--- /dev/null
+++ b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2010 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 INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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 PluginInfoStore_h
+#define PluginInfoStore_h
+
+#include "PluginModuleInfo.h"
+
+namespace WebCore {
+ class KURL;
+}
+
+namespace WebKit {
+
+class PluginInfoStore {
+ WTF_MAKE_NONCOPYABLE(PluginInfoStore);
+
+public:
+ PluginInfoStore();
+
+ void setAdditionalPluginsDirectories(const Vector<String>&);
+
+ void refresh();
+ Vector<PluginModuleInfo> plugins();
+
+ // Returns the info for a plug-in that can handle the given MIME type.
+ // If the MIME type is null, the file extension of the given url will be used to infer the
+ // plug-in type. In that case, mimeType will be filled in with the right MIME type.
+ PluginModuleInfo findPlugin(String& mimeType, const WebCore::KURL&);
+
+ // Returns the info for the plug-in with the given path.
+ PluginModuleInfo infoForPluginWithPath(const String& pluginPath) const;
+
+private:
+
+ PluginModuleInfo findPluginForMIMEType(const String& mimeType) const;
+ PluginModuleInfo findPluginForExtension(const String& extension, String& mimeType) const;
+
+ void loadPluginsIfNecessary();
+ static void loadPlugin(Vector<PluginModuleInfo>& plugins, const String& pluginPath);
+
+ // Platform-specific member functions:
+
+ // Returns paths to directories that should be searched for plug-ins (via pluginPathsInDirectory).
+ static Vector<String> pluginsDirectories();
+
+ // Returns paths to all plug-ins in the specified directory.
+ static Vector<String> pluginPathsInDirectory(const String& directory);
+
+ // Returns paths to individual plug-ins that won't be found via pluginsDirectories/pluginPathsInDirectory.
+ static Vector<String> individualPluginPaths();
+
+ // Load plug-in info for the plug-in with the specified path.
+ static bool getPluginInfo(const String& pluginPath, PluginModuleInfo&);
+
+ // Return whether this plug-in should be used (added to the list of plug-ins) or not.
+ static bool shouldUsePlugin(Vector<PluginModuleInfo>& alreadyLoadedPlugins, const PluginModuleInfo&);
+
+ // Get the MIME type for the given extension.
+ static String getMIMETypeForExtension(const String& extension);
+
+ Vector<String> m_additionalPluginsDirectories;
+ Vector<PluginModuleInfo> m_plugins;
+ bool m_pluginListIsUpToDate;
+};
+
+} // namespace WebKit
+
+#endif // PluginInfoStore_h
diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp
new file mode 100644
index 000000000..35da365d7
--- /dev/null
+++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2010 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 INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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 "PluginProcessManager.h"
+
+#if ENABLE(PLUGIN_PROCESS)
+
+#include "PluginProcessProxy.h"
+#include "WebContext.h"
+#include <wtf/StdLibExtras.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+
+PluginProcessManager& PluginProcessManager::shared()
+{
+ DEFINE_STATIC_LOCAL(PluginProcessManager, pluginProcessManager, ());
+ return pluginProcessManager;
+}
+
+PluginProcessManager::PluginProcessManager()
+{
+}
+
+void PluginProcessManager::getPluginProcessConnection(const PluginInfoStore& pluginInfoStore, const String& pluginPath, PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply)
+{
+ ASSERT(!pluginPath.isNull());
+
+ PluginModuleInfo plugin = pluginInfoStore.infoForPluginWithPath(pluginPath);
+ PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(plugin);
+ pluginProcess->getPluginProcessConnection(reply);
+}
+
+void PluginProcessManager::removePluginProcessProxy(PluginProcessProxy* pluginProcessProxy)
+{
+ size_t vectorIndex = m_pluginProcesses.find(pluginProcessProxy);
+ ASSERT(vectorIndex != notFound);
+
+ m_pluginProcesses.remove(vectorIndex);
+}
+
+void PluginProcessManager::getSitesWithData(const PluginModuleInfo& plugin, WebPluginSiteDataManager* webPluginSiteDataManager, uint64_t callbackID)
+{
+ PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(plugin);
+ pluginProcess->getSitesWithData(webPluginSiteDataManager, callbackID);
+}
+
+void PluginProcessManager::clearSiteData(const PluginModuleInfo& plugin, WebPluginSiteDataManager* webPluginSiteDataManager, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID)
+{
+ PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(plugin);
+ pluginProcess->clearSiteData(webPluginSiteDataManager, sites, flags, maxAgeInSeconds, callbackID);
+}
+
+void PluginProcessManager::pluginSyncMessageSendTimedOut(const String& pluginPath)
+{
+ PluginProcessProxy* pluginProcess = pluginProcessWithPath(pluginPath);
+ if (!pluginProcess)
+ return;
+
+ pluginProcess->terminate();
+}
+
+PluginProcessProxy* PluginProcessManager::pluginProcessWithPath(const String& pluginPath)
+{
+ for (size_t i = 0; i < m_pluginProcesses.size(); ++i) {
+ if (m_pluginProcesses[i]->pluginInfo().path == pluginPath)
+ return m_pluginProcesses[i];
+ }
+ return 0;
+}
+
+PluginProcessProxy* PluginProcessManager::getOrCreatePluginProcess(const PluginModuleInfo& plugin)
+{
+ if (PluginProcessProxy* pluginProcess = pluginProcessWithPath(plugin.path))
+ return pluginProcess;
+
+ PluginProcessProxy* pluginProcess = PluginProcessProxy::create(this, plugin).leakPtr();
+ m_pluginProcesses.append(pluginProcess);
+
+ return pluginProcess;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(PLUGIN_PROCESS)
diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h
new file mode 100644
index 000000000..935967bdd
--- /dev/null
+++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 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 INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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 PluginProcessManager_h
+#define PluginProcessManager_h
+
+#if ENABLE(PLUGIN_PROCESS)
+
+#include "PluginModuleInfo.h"
+#include "WebProcessProxyMessages.h"
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+
+namespace CoreIPC {
+ class ArgumentEncoder;
+}
+
+namespace WebKit {
+
+class PluginInfoStore;
+class PluginProcessProxy;
+class WebProcessProxy;
+class WebPluginSiteDataManager;
+
+class PluginProcessManager {
+ WTF_MAKE_NONCOPYABLE(PluginProcessManager);
+public:
+ static PluginProcessManager& shared();
+
+ void getPluginProcessConnection(const PluginInfoStore&, const String& pluginPath, PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply>);
+ void removePluginProcessProxy(PluginProcessProxy*);
+
+ void getSitesWithData(const PluginModuleInfo&, WebPluginSiteDataManager*, uint64_t callbackID);
+ void clearSiteData(const PluginModuleInfo&, WebPluginSiteDataManager*, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID);
+
+ void pluginSyncMessageSendTimedOut(const String& pluginPath);
+
+private:
+ PluginProcessManager();
+
+ PluginProcessProxy* getOrCreatePluginProcess(const PluginModuleInfo&);
+ PluginProcessProxy* pluginProcessWithPath(const String& pluginPath);
+
+ Vector<PluginProcessProxy*> m_pluginProcesses;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(PLUGIN_PROCESS)
+
+#endif // PluginProcessManager_h
diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp
new file mode 100644
index 000000000..41c7a47cb
--- /dev/null
+++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2010 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 INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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 "PluginProcessProxy.h"
+
+#if ENABLE(PLUGIN_PROCESS)
+
+#include "PluginProcessCreationParameters.h"
+#include "PluginProcessManager.h"
+#include "PluginProcessMessages.h"
+#include "RunLoop.h"
+#include "WebContext.h"
+#include "WebCoreArgumentCoders.h"
+#include "WebPluginSiteDataManager.h"
+#include "WebProcessMessages.h"
+#include "WebProcessProxy.h"
+#include <WebCore/NotImplemented.h>
+
+#if PLATFORM(MAC)
+#include "MachPort.h"
+#endif
+
+namespace WebKit {
+
+PassOwnPtr<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginModuleInfo& pluginInfo)
+{
+ return adoptPtr(new PluginProcessProxy(PluginProcessManager, pluginInfo));
+}
+
+PluginProcessProxy::PluginProcessProxy(PluginProcessManager* PluginProcessManager, const PluginModuleInfo& pluginInfo)
+ : m_pluginProcessManager(PluginProcessManager)
+ , m_pluginInfo(pluginInfo)
+ , m_numPendingConnectionRequests(0)
+#if PLATFORM(MAC)
+ , m_modalWindowIsShowing(false)
+ , m_fullscreenWindowIsShowing(false)
+ , m_preFullscreenAppPresentationOptions(0)
+#endif
+{
+ ProcessLauncher::LaunchOptions launchOptions;
+ launchOptions.processType = ProcessLauncher::PluginProcess;
+#if PLATFORM(MAC)
+ launchOptions.architecture = pluginInfo.pluginArchitecture;
+ launchOptions.executableHeap = PluginProcessProxy::pluginNeedsExecutableHeap(pluginInfo);
+#endif
+
+ m_processLauncher = ProcessLauncher::create(this, launchOptions);
+}
+
+PluginProcessProxy::~PluginProcessProxy()
+{
+}
+
+// Asks the plug-in process to create a new connection to a web process. The connection identifier will be
+// encoded in the given argument encoder and sent back to the connection of the given web process.
+void PluginProcessProxy::getPluginProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply)
+{
+ m_pendingConnectionReplies.append(reply);
+
+ if (m_processLauncher->isLaunching()) {
+ m_numPendingConnectionRequests++;
+ return;
+ }
+
+ // Ask the plug-in process to create a connection. Since the plug-in can be waiting for a synchronous reply
+ // we need to make sure that this message is always processed, even when the plug-in is waiting for a synchronus reply.
+ m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0, CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply);
+}
+
+void PluginProcessProxy::getSitesWithData(WebPluginSiteDataManager* webPluginSiteDataManager, uint64_t callbackID)
+{
+ ASSERT(!m_pendingGetSitesReplies.contains(callbackID));
+ m_pendingGetSitesReplies.set(callbackID, webPluginSiteDataManager);
+
+ if (m_processLauncher->isLaunching()) {
+ m_pendingGetSitesRequests.append(callbackID);
+ return;
+ }
+
+ // Ask the plug-in process for the sites with data.
+ m_connection->send(Messages::PluginProcess::GetSitesWithData(callbackID), 0);
+}
+
+void PluginProcessProxy::clearSiteData(WebPluginSiteDataManager* webPluginSiteDataManager, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID)
+{
+ ASSERT(!m_pendingClearSiteDataReplies.contains(callbackID));
+ m_pendingClearSiteDataReplies.set(callbackID, webPluginSiteDataManager);
+
+ if (m_processLauncher->isLaunching()) {
+ ClearSiteDataRequest request;
+ request.sites = sites;
+ request.flags = flags;
+ request.maxAgeInSeconds = maxAgeInSeconds;
+ request.callbackID = callbackID;
+ m_pendingClearSiteDataRequests.append(request);
+ return;
+ }
+
+ // Ask the plug-in process to clear the site data.
+ m_connection->send(Messages::PluginProcess::ClearSiteData(sites, flags, maxAgeInSeconds, callbackID), 0);
+}
+
+void PluginProcessProxy::terminate()
+{
+ m_processLauncher->terminateProcess();
+}
+
+void PluginProcessProxy::pluginProcessCrashedOrFailedToLaunch()
+{
+ // The plug-in process must have crashed or exited, send any pending sync replies we might have.
+ while (!m_pendingConnectionReplies.isEmpty()) {
+ RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply = m_pendingConnectionReplies.takeFirst();
+
+#if PLATFORM(MAC)
+ reply->send(CoreIPC::Attachment(0, MACH_MSG_TYPE_MOVE_SEND));
+#elif USE(UNIX_DOMAIN_SOCKETS)
+ reply->send(CoreIPC::Attachment());
+#else
+ notImplemented();
+#endif
+ }
+
+ while (!m_pendingGetSitesReplies.isEmpty())
+ didGetSitesWithData(Vector<String>(), m_pendingGetSitesReplies.begin()->first);
+
+ while (!m_pendingClearSiteDataReplies.isEmpty())
+ didClearSiteData(m_pendingClearSiteDataReplies.begin()->first);
+
+ // Tell the plug-in process manager to forget about this plug-in process proxy.
+ m_pluginProcessManager->removePluginProcessProxy(this);
+ delete this;
+}
+
+void PluginProcessProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
+{
+ didReceivePluginProcessProxyMessage(connection, messageID, arguments);
+}
+
+void PluginProcessProxy::didClose(CoreIPC::Connection*)
+{
+#if PLATFORM(MAC)
+ if (m_modalWindowIsShowing)
+ endModal();
+
+ if (m_fullscreenWindowIsShowing)
+ exitFullscreen();
+#endif
+
+ const Vector<WebContext*>& contexts = WebContext::allContexts();
+ for (size_t i = 0; i < contexts.size(); ++i)
+ contexts[i]->sendToAllProcesses(Messages::WebProcess::PluginProcessCrashed(m_pluginInfo.path));
+
+ // This will cause us to be deleted.
+ pluginProcessCrashedOrFailedToLaunch();
+}
+
+void PluginProcessProxy::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID)
+{
+}
+
+void PluginProcessProxy::syncMessageSendTimedOut(CoreIPC::Connection*)
+{
+}
+
+void PluginProcessProxy::didFinishLaunching(ProcessLauncher*, CoreIPC::Connection::Identifier connectionIdentifier)
+{
+ ASSERT(!m_connection);
+
+ if (!connectionIdentifier) {
+ pluginProcessCrashedOrFailedToLaunch();
+ return;
+ }
+
+ m_connection = CoreIPC::Connection::createServerConnection(connectionIdentifier, this, RunLoop::main());
+#if PLATFORM(MAC)
+ m_connection->setShouldCloseConnectionOnMachExceptions();
+#endif
+
+ m_connection->open();
+
+ PluginProcessCreationParameters parameters;
+
+ parameters.pluginPath = m_pluginInfo.path;
+
+ platformInitializePluginProcess(parameters);
+
+ // Initialize the plug-in host process.
+ m_connection->send(Messages::PluginProcess::InitializePluginProcess(parameters), 0);
+
+ // Send all our pending requests.
+ for (size_t i = 0; i < m_pendingGetSitesRequests.size(); ++i)
+ m_connection->send(Messages::PluginProcess::GetSitesWithData(m_pendingGetSitesRequests[i]), 0);
+ m_pendingGetSitesRequests.clear();
+
+ for (size_t i = 0; i < m_pendingClearSiteDataRequests.size(); ++i) {
+ const ClearSiteDataRequest& request = m_pendingClearSiteDataRequests[i];
+ m_connection->send(Messages::PluginProcess::ClearSiteData(request.sites, request.flags, request.maxAgeInSeconds, request.callbackID), 0);
+ }
+ m_pendingClearSiteDataRequests.clear();
+
+ for (unsigned i = 0; i < m_numPendingConnectionRequests; ++i)
+ m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0);
+
+ m_numPendingConnectionRequests = 0;
+}
+
+void PluginProcessProxy::didCreateWebProcessConnection(const CoreIPC::Attachment& connectionIdentifier)
+{
+ ASSERT(!m_pendingConnectionReplies.isEmpty());
+
+ // Grab the first pending connection reply.
+ RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply = m_pendingConnectionReplies.takeFirst();
+
+#if PLATFORM(MAC)
+ reply->send(CoreIPC::Attachment(connectionIdentifier.port(), MACH_MSG_TYPE_MOVE_SEND));
+#elif USE(UNIX_DOMAIN_SOCKETS)
+ reply->send(connectionIdentifier);
+#else
+ notImplemented();
+#endif
+}
+
+void PluginProcessProxy::didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID)
+{
+ RefPtr<WebPluginSiteDataManager> webPluginSiteDataManager = m_pendingGetSitesReplies.take(callbackID);
+ ASSERT(webPluginSiteDataManager);
+
+ webPluginSiteDataManager->didGetSitesWithDataForSinglePlugin(sites, callbackID);
+}
+
+void PluginProcessProxy::didClearSiteData(uint64_t callbackID)
+{
+ RefPtr<WebPluginSiteDataManager> webPluginSiteDataManager = m_pendingClearSiteDataReplies.take(callbackID);
+ ASSERT(webPluginSiteDataManager);
+
+ webPluginSiteDataManager->didClearSiteDataForSinglePlugin(callbackID);
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(PLUGIN_PROCESS)
diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h
new file mode 100644
index 000000000..a75d5b138
--- /dev/null
+++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2010 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 INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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 PluginProcessProxy_h
+#define PluginProcessProxy_h
+
+#if ENABLE(PLUGIN_PROCESS)
+
+#include "Connection.h"
+#include "PluginModuleInfo.h"
+#include "ProcessLauncher.h"
+#include "WebProcessProxyMessages.h"
+#include <wtf/Deque.h>
+
+#if PLATFORM(MAC)
+#include <wtf/RetainPtr.h>
+OBJC_CLASS NSObject;
+OBJC_CLASS WKPlaceholderModalWindow;
+#endif
+
+// FIXME: This is platform specific.
+namespace CoreIPC {
+ class MachPort;
+}
+
+namespace WebKit {
+
+class PluginProcessManager;
+class WebPluginSiteDataManager;
+class WebProcessProxy;
+struct PluginProcessCreationParameters;
+
+class PluginProcessProxy : CoreIPC::Connection::Client, ProcessLauncher::Client {
+public:
+ static PassOwnPtr<PluginProcessProxy> create(PluginProcessManager*, const PluginModuleInfo&);
+ ~PluginProcessProxy();
+
+ const PluginModuleInfo& pluginInfo() const { return m_pluginInfo; }
+
+ // Asks the plug-in process to create a new connection to a web process. The connection identifier will be
+ // encoded in the given argument encoder and sent back to the connection of the given web process.
+ void getPluginProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply>);
+
+ // Asks the plug-in process to get a list of domains for which the plug-in has data stored.
+ void getSitesWithData(WebPluginSiteDataManager*, uint64_t callbackID);
+
+ // Asks the plug-in process to clear the data for the given sites.
+ void clearSiteData(WebPluginSiteDataManager*, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID);
+
+ // Terminates the plug-in process.
+ void terminate();
+
+#if PLATFORM(MAC)
+ // Returns whether the plug-in needs the heap to be marked executable.
+ static bool pluginNeedsExecutableHeap(const PluginModuleInfo&);
+
+ // Creates a property list in ~/Library/Preferences that contains all the MIME types supported by the plug-in.
+ static bool createPropertyListFile(const PluginModuleInfo&);
+#endif
+
+private:
+ PluginProcessProxy(PluginProcessManager*, const PluginModuleInfo&);
+
+ void pluginProcessCrashedOrFailedToLaunch();
+
+ // CoreIPC::Connection::Client
+ virtual void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*);
+ virtual void didClose(CoreIPC::Connection*);
+ virtual void didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID);
+ virtual void syncMessageSendTimedOut(CoreIPC::Connection*);
+
+ // ProcessLauncher::Client
+ virtual void didFinishLaunching(ProcessLauncher*, CoreIPC::Connection::Identifier);
+
+ // Message handlers
+ void didReceivePluginProcessProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*);
+ void didCreateWebProcessConnection(const CoreIPC::Attachment&);
+ void didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID);
+ void didClearSiteData(uint64_t callbackID);
+
+#if PLATFORM(MAC)
+ bool getPluginProcessSerialNumber(ProcessSerialNumber&);
+ void makePluginProcessTheFrontProcess();
+ void makeUIProcessTheFrontProcess();
+
+ void setFullscreenWindowIsShowing(bool);
+ void enterFullscreen();
+ void exitFullscreen();
+
+ void setModalWindowIsShowing(bool);
+ void beginModal();
+ void endModal();
+
+ void applicationDidBecomeActive();
+#endif
+
+ void platformInitializePluginProcess(PluginProcessCreationParameters& parameters);
+
+ // The plug-in host process manager.
+ PluginProcessManager* m_pluginProcessManager;
+
+ // Information about the plug-in.
+ PluginModuleInfo m_pluginInfo;
+
+ // The connection to the plug-in host process.
+ RefPtr<CoreIPC::Connection> m_connection;
+
+ // The process launcher for the plug-in host process.
+ RefPtr<ProcessLauncher> m_processLauncher;
+
+ Deque<RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> > m_pendingConnectionReplies;
+
+ Vector<uint64_t> m_pendingGetSitesRequests;
+ HashMap<uint64_t, RefPtr<WebPluginSiteDataManager> > m_pendingGetSitesReplies;
+
+ struct ClearSiteDataRequest {
+ Vector<String> sites;
+ uint64_t flags;
+ uint64_t maxAgeInSeconds;
+ uint64_t callbackID;
+ };
+ Vector<ClearSiteDataRequest> m_pendingClearSiteDataRequests;
+ HashMap<uint64_t, RefPtr<WebPluginSiteDataManager> > m_pendingClearSiteDataReplies;
+
+ // If createPluginConnection is called while the process is still launching we'll keep count of it and send a bunch of requests
+ // when the process finishes launching.
+ unsigned m_numPendingConnectionRequests;
+
+#if PLATFORM(MAC)
+ RetainPtr<NSObject> m_activationObserver;
+ RetainPtr<WKPlaceholderModalWindow *> m_placeholderWindow;
+ bool m_modalWindowIsShowing;
+ bool m_fullscreenWindowIsShowing;
+ unsigned m_preFullscreenAppPresentationOptions;
+#endif
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(PLUGIN_PROCESS)
+
+#endif // PluginProcessProxy_h
diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in
new file mode 100644
index 000000000..7b59aefec
--- /dev/null
+++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in
@@ -0,0 +1,37 @@
+# Copyright (C) 2010 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 INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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.
+
+#if ENABLE(PLUGIN_PROCESS)
+
+messages -> PluginProcessProxy {
+ DidCreateWebProcessConnection(CoreIPC::Attachment connectionIdentifier)
+
+ DidGetSitesWithData(Vector<WTF::String> sites, uint64_t callbackID)
+ DidClearSiteData(uint64_t callbackID)
+
+#if PLATFORM(MAC)
+ SetModalWindowIsShowing(bool modalWindowIsShowing)
+ SetFullscreenWindowIsShowing(bool fullscreenWindowIsShowing)
+#endif
+}
+
+#endif
diff --git a/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp b/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp
new file mode 100644
index 000000000..553ea727b
--- /dev/null
+++ b/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2011 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 INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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 "WebPluginSiteDataManager.h"
+
+#include "ImmutableArray.h"
+#include "PluginProcessManager.h"
+#include "WebContext.h"
+#include "WebProcessMessages.h"
+
+using namespace WebCore;
+
+namespace WebKit {
+
+#if ENABLE(PLUGIN_PROCESS)
+class WebPluginSiteDataManager::GetSitesWithDataState {
+public:
+ explicit GetSitesWithDataState(WebPluginSiteDataManager* webPluginSiteDataManager, uint64_t callbackID)
+ : m_webPluginSiteDataManager(webPluginSiteDataManager)
+ , m_callbackID(callbackID)
+ , m_plugins(webPluginSiteDataManager->m_webContext->pluginInfoStore().plugins())
+ {
+ }
+
+ void getSitesWithDataForNextPlugin()
+ {
+ if (m_plugins.isEmpty()) {
+ Vector<String> sites;
+ copyToVector(m_sites, sites);
+
+ m_webPluginSiteDataManager->didGetSitesWithDataForAllPlugins(sites, m_callbackID);
+ return;
+ }
+
+ PluginProcessManager::shared().getSitesWithData(m_plugins.last(), m_webPluginSiteDataManager, m_callbackID);
+ m_plugins.removeLast();
+ }
+
+ void didGetSitesWithDataForSinglePlugin(const Vector<String>& sites)
+ {
+ for (size_t i = 0; i < sites.size(); ++i)
+ m_sites.add(sites[i]);
+
+ getSitesWithDataForNextPlugin();
+ }
+
+private:
+ WebPluginSiteDataManager* m_webPluginSiteDataManager;
+ uint64_t m_callbackID;
+ Vector<PluginModuleInfo> m_plugins;
+ HashSet<String> m_sites;
+};
+
+class WebPluginSiteDataManager::ClearSiteDataState {
+public:
+ explicit ClearSiteDataState(WebPluginSiteDataManager* webPluginSiteDataManager, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID)
+ : m_webPluginSiteDataManager(webPluginSiteDataManager)
+ , m_sites(sites)
+ , m_flags(flags)
+ , m_maxAgeInSeconds(maxAgeInSeconds)
+ , m_callbackID(callbackID)
+ , m_plugins(webPluginSiteDataManager->m_webContext->pluginInfoStore().plugins())
+ {
+ }
+
+ void clearSiteDataForNextPlugin()
+ {
+ if (m_plugins.isEmpty()) {
+ m_webPluginSiteDataManager->didClearSiteDataForAllPlugins(m_callbackID);
+ return;
+ }
+
+ PluginProcessManager::shared().clearSiteData(m_plugins.last(), m_webPluginSiteDataManager, m_sites, m_flags, m_maxAgeInSeconds, m_callbackID);
+ m_plugins.removeLast();
+ }
+
+ void didClearSiteDataForSinglePlugin()
+ {
+ clearSiteDataForNextPlugin();
+ }
+
+private:
+ WebPluginSiteDataManager* m_webPluginSiteDataManager;
+ Vector<String> m_sites;
+ uint64_t m_flags;
+ uint64_t m_maxAgeInSeconds;
+ uint64_t m_callbackID;
+ Vector<PluginModuleInfo> m_plugins;
+};
+#endif // ENABLE(PLUGIN_PROCESS)
+
+PassRefPtr<WebPluginSiteDataManager> WebPluginSiteDataManager::create(WebContext* webContext)
+{
+ return adoptRef(new WebPluginSiteDataManager(webContext));
+}
+
+WebPluginSiteDataManager::WebPluginSiteDataManager(WebContext* webContext)
+ : m_webContext(webContext)
+{
+}
+
+WebPluginSiteDataManager::~WebPluginSiteDataManager()
+{
+ ASSERT(m_arrayCallbacks.isEmpty());
+ ASSERT(m_voidCallbacks.isEmpty());
+#if ENABLE(PLUGIN_PROCESS)
+ ASSERT(m_pendingGetSitesWithData.isEmpty());
+ ASSERT(m_pendingClearSiteData.isEmpty());
+#endif
+}
+
+void WebPluginSiteDataManager::invalidate()
+{
+ invalidateCallbackMap(m_arrayCallbacks);
+
+#if ENABLE(PLUGIN_PROCESS)
+ deleteAllValues(m_pendingGetSitesWithData);
+ m_pendingGetSitesWithData.clear();
+ deleteAllValues(m_pendingClearSiteData);
+ m_pendingClearSiteData.clear();
+#endif
+}
+
+void WebPluginSiteDataManager::getSitesWithData(PassRefPtr<ArrayCallback> prpCallback)
+{
+ RefPtr<ArrayCallback> callback = prpCallback;
+
+ if (!m_webContext) {
+ callback->invalidate();
+ return;
+ }
+
+ uint64_t callbackID = callback->callbackID();
+ m_arrayCallbacks.set(callbackID, callback.release());
+
+#if ENABLE(PLUGIN_PROCESS)
+ ASSERT(!m_pendingGetSitesWithData.contains(callbackID));
+
+ GetSitesWithDataState* state = new GetSitesWithDataState(this, callbackID);
+ m_pendingGetSitesWithData.set(callbackID, state);
+ state->getSitesWithDataForNextPlugin();
+#else
+ m_webContext->relaunchProcessIfNecessary();
+
+ Vector<PluginModuleInfo> plugins = m_webContext->pluginInfoStore().plugins();
+ Vector<String> pluginPaths;
+ for (size_t i = 0; i < plugins.size(); ++i)
+ pluginPaths.append(plugins[i].path);
+
+ // FIXME (Multi-WebProcess): When multi-process is enabled, we must always use a plug-in process for this,
+ // so this code should just be removed.
+ m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebProcess::GetSitesWithPluginData(pluginPaths, callbackID));
+#endif
+}
+
+void WebPluginSiteDataManager::didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID)
+{
+ RefPtr<ArrayCallback> callback = m_arrayCallbacks.take(callbackID);
+ if (!callback) {
+ // FIXME: Log error or assert.
+ return;
+ }
+
+ Vector<RefPtr<APIObject> > sitesWK(sites.size());
+
+ for (size_t i = 0; i < sites.size(); ++i)
+ sitesWK[i] = WebString::create(sites[i]);
+
+ RefPtr<ImmutableArray> resultArray = ImmutableArray::adopt(sitesWK);
+ callback->performCallbackWithReturnValue(resultArray.get());
+}
+
+void WebPluginSiteDataManager::clearSiteData(ImmutableArray* sites, uint64_t flags, uint64_t maxAgeInSeconds, PassRefPtr<VoidCallback> prpCallback)
+{
+ RefPtr<VoidCallback> callback = prpCallback;
+ if (!m_webContext) {
+ callback->invalidate();
+ return;
+ }
+
+ Vector<String> sitesVector;
+
+ // If the array is empty, don't do anything.
+ if (sites) {
+ if (!sites->size()) {
+ callback->performCallback();
+ return;
+ }
+
+ for (size_t i = 0; i < sites->size(); ++i) {
+ if (WebString* site = sites->at<WebString>(i))
+ sitesVector.append(site->string());
+ }
+ }
+
+ uint64_t callbackID = callback->callbackID();
+ m_voidCallbacks.set(callbackID, callback.release());
+
+#if ENABLE(PLUGIN_PROCESS)
+ ASSERT(!m_pendingClearSiteData.contains(callbackID));
+
+ ClearSiteDataState* state = new ClearSiteDataState(this, sitesVector, flags, maxAgeInSeconds, callbackID);
+ m_pendingClearSiteData.set(callbackID, state);
+ state->clearSiteDataForNextPlugin();
+#else
+ m_webContext->relaunchProcessIfNecessary();
+
+ Vector<PluginModuleInfo> plugins = m_webContext->pluginInfoStore().plugins();
+ Vector<String> pluginPaths;
+ for (size_t i = 0; i < plugins.size(); ++i)
+ pluginPaths.append(plugins[i].path);
+
+ // FIXME (Multi-WebProcess): When multi-process is enabled, we must always use a plug-in process for this,
+ // so this code should just be removed.
+ m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebProcess::ClearPluginSiteData(pluginPaths, sitesVector, flags, maxAgeInSeconds, callbackID));
+#endif
+}
+
+void WebPluginSiteDataManager::didClearSiteData(uint64_t callbackID)
+{
+ RefPtr<VoidCallback> callback = m_voidCallbacks.take(callbackID);
+ if (!callback) {
+ // FIXME: Log error or assert.
+ return;
+ }
+
+ callback->performCallback();
+}
+
+bool WebPluginSiteDataManager::shouldTerminate(WebProcessProxy*) const
+{
+#if ENABLE(PLUGIN_PROCESS)
+ // When out of process plug-ins are enabled, the web process is not involved in fetching site data.
+ return true;
+#else
+ return m_arrayCallbacks.isEmpty() && m_voidCallbacks.isEmpty();
+#endif
+}
+
+#if ENABLE(PLUGIN_PROCESS)
+void WebPluginSiteDataManager::didGetSitesWithDataForSinglePlugin(const Vector<String>& sites, uint64_t callbackID)
+{
+ GetSitesWithDataState* state = m_pendingGetSitesWithData.get(callbackID);
+ ASSERT(state);
+
+ state->didGetSitesWithDataForSinglePlugin(sites);
+}
+
+void WebPluginSiteDataManager::didGetSitesWithDataForAllPlugins(const Vector<String>& sites, uint64_t callbackID)
+{
+ OwnPtr<GetSitesWithDataState> state = adoptPtr(m_pendingGetSitesWithData.take(callbackID));
+ ASSERT(state);
+
+ didGetSitesWithData(sites, callbackID);
+}
+
+void WebPluginSiteDataManager::didClearSiteDataForSinglePlugin(uint64_t callbackID)
+{
+ ClearSiteDataState* state = m_pendingClearSiteData.get(callbackID);
+ ASSERT(state);
+
+ state->didClearSiteDataForSinglePlugin();
+}
+
+void WebPluginSiteDataManager::didClearSiteDataForAllPlugins(uint64_t callbackID)
+{
+ OwnPtr<ClearSiteDataState> state = adoptPtr(m_pendingClearSiteData.take(callbackID));
+ ASSERT(state);
+
+ didClearSiteData(callbackID);
+}
+
+#endif
+
+} // namespace WebKit
+
diff --git a/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.h b/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.h
new file mode 100644
index 000000000..9efa17513
--- /dev/null
+++ b/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2011 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 INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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 WebPluginSiteDataManagerh
+#define WebPluginSiteDataManager_h
+
+#include "APIObject.h"
+#include "Arguments.h"
+#include "GenericCallback.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebKit {
+
+class WebContext;
+class WebProcessProxy;
+
+typedef GenericCallback<WKArrayRef> ArrayCallback;
+
+class WebPluginSiteDataManager : public APIObject {
+public:
+ static const Type APIType = TypePluginSiteDataManager;
+
+ static PassRefPtr<WebPluginSiteDataManager> create(WebContext*);
+ virtual ~WebPluginSiteDataManager();
+
+ void invalidate();
+ void clearContext() { m_webContext = 0; }
+
+ void getSitesWithData(PassRefPtr<ArrayCallback>);
+ void didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID);
+
+ void clearSiteData(ImmutableArray* sites, uint64_t flags, uint64_t maxAgeInSeconds, PassRefPtr<VoidCallback>);
+ void didClearSiteData(uint64_t callbackID);
+
+#if ENABLE(PLUGIN_PROCESS)
+ void didGetSitesWithDataForSinglePlugin(const Vector<String>& sites, uint64_t callbackID);
+ void didClearSiteDataForSinglePlugin(uint64_t callbackID);
+#endif
+
+ bool shouldTerminate(WebProcessProxy*) const;
+
+private:
+ explicit WebPluginSiteDataManager(WebContext*);
+
+ virtual Type type() const { return APIType; }
+
+ WebContext* m_webContext;
+ HashMap<uint64_t, RefPtr<ArrayCallback> > m_arrayCallbacks;
+ HashMap<uint64_t, RefPtr<VoidCallback> > m_voidCallbacks;
+
+#if ENABLE(PLUGIN_PROCESS)
+ void didGetSitesWithDataForAllPlugins(const Vector<String>& sites, uint64_t callbackID);
+ void didClearSiteDataForAllPlugins(uint64_t callbackID);
+
+ class GetSitesWithDataState;
+ HashMap<uint64_t, GetSitesWithDataState*> m_pendingGetSitesWithData;
+
+ class ClearSiteDataState;
+ HashMap<uint64_t, ClearSiteDataState*> m_pendingClearSiteData;
+#endif
+};
+
+} // namespace WebKit
+
+#endif // WebPluginSiteDataManager_h
diff --git a/Source/WebKit2/UIProcess/Plugins/gtk/PluginProcessProxyGtk.cpp b/Source/WebKit2/UIProcess/Plugins/gtk/PluginProcessProxyGtk.cpp
new file mode 100644
index 000000000..4c85772a2
--- /dev/null
+++ b/Source/WebKit2/UIProcess/Plugins/gtk/PluginProcessProxyGtk.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * 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 INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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 "PluginProcessProxy.h"
+
+#if ENABLE(PLUGIN_PROCESS)
+
+#include "PluginProcessCreationParameters.h"
+#include <WebCore/NotImplemented.h>
+
+namespace WebKit {
+
+void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationParameters& parameters)
+{
+ notImplemented();
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(PLUGIN_PROCESS)
diff --git a/Source/WebKit2/UIProcess/Plugins/mac/PluginInfoStoreMac.mm b/Source/WebKit2/UIProcess/Plugins/mac/PluginInfoStoreMac.mm
new file mode 100644
index 000000000..6c6040781
--- /dev/null
+++ b/Source/WebKit2/UIProcess/Plugins/mac/PluginInfoStoreMac.mm
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2010 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 INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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.
+ */
+
+#import "config.h"
+#import "PluginInfoStore.h"
+
+#import "NetscapePluginModule.h"
+#import "WebKitSystemInterface.h"
+#import <WebCore/WebCoreNSStringExtras.h>
+#import <wtf/HashSet.h>
+#import <wtf/RetainPtr.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+Vector<String> PluginInfoStore::pluginsDirectories()
+{
+ Vector<String> pluginsDirectories;
+
+ pluginsDirectories.append([NSHomeDirectory() stringByAppendingPathComponent:@"Library/Internet Plug-Ins"]);
+ pluginsDirectories.append("/Library/Internet Plug-Ins");
+
+ return pluginsDirectories;
+}
+
+// FIXME: Once the UI process knows the difference between the main thread and the web thread we can drop this and just use
+// String::createCFString.
+static CFStringRef safeCreateCFString(const String& string)
+{
+ return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar*>(string.characters()), string.length());
+}
+
+Vector<String> PluginInfoStore::pluginPathsInDirectory(const String& directory)
+{
+ Vector<String> pluginPaths;
+
+ RetainPtr<CFStringRef> directoryCFString(AdoptCF, safeCreateCFString(directory));
+
+ NSArray *filenames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:(NSString *)directoryCFString.get() error:nil];
+ for (NSString *filename in filenames)
+ pluginPaths.append([(NSString *)directoryCFString.get() stringByAppendingPathComponent:filename]);
+
+ return pluginPaths;
+}
+
+Vector<String> PluginInfoStore::individualPluginPaths()
+{
+ return Vector<String>();
+}
+
+bool PluginInfoStore::getPluginInfo(const String& pluginPath, PluginModuleInfo& plugin)
+{
+ return NetscapePluginModule::getPluginInfo(pluginPath, plugin);
+}
+
+bool PluginInfoStore::shouldUsePlugin(Vector<PluginModuleInfo>& alreadyLoadedPlugins, const PluginModuleInfo& plugin)
+{
+ for (size_t i = 0; i < alreadyLoadedPlugins.size(); ++i) {
+ const PluginModuleInfo& loadedPlugin = alreadyLoadedPlugins[i];
+
+ // If a plug-in with the same bundle identifier already exists, we don't want to load it.
+ if (loadedPlugin.bundleIdentifier == plugin.bundleIdentifier)
+ return false;
+ }
+
+ return true;
+}
+
+String PluginInfoStore::getMIMETypeForExtension(const String& extension)
+{
+ // FIXME: This should just call MIMETypeRegistry::getMIMETypeForExtension and be
+ // strength reduced into the callsite once we can safely convert String
+ // to CFStringRef off the main thread.
+
+ RetainPtr<CFStringRef> extensionCFString(AdoptCF, safeCreateCFString(extension));
+ return WKGetMIMETypeForExtension((NSString *)extensionCFString.get());
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm b/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm
new file mode 100644
index 000000000..b072417fe
--- /dev/null
+++ b/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2010 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 INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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.
+ */
+
+#import "config.h"
+#import "PluginProcessProxy.h"
+
+#if ENABLE(PLUGIN_PROCESS)
+
+#import "EnvironmentVariables.h"
+#import "PluginProcessCreationParameters.h"
+#import "WebKitSystemInterface.h"
+#import <WebCore/FileSystem.h>
+#import <spawn.h>
+#import <wtf/text/CString.h>
+
+@interface WKPlaceholderModalWindow : NSWindow
+@end
+
+@implementation WKPlaceholderModalWindow
+
+// Prevent NSApp from calling requestUserAttention: when the window is shown
+// modally, even if the app is inactive. See 6823049.
+- (BOOL)_wantsUserAttention
+{
+ return NO;
+}
+
+@end
+
+using namespace WebCore;
+
+namespace WebKit {
+
+bool PluginProcessProxy::pluginNeedsExecutableHeap(const PluginModuleInfo& pluginInfo)
+{
+ static bool forceNonexecutableHeapForPlugins = [[NSUserDefaults standardUserDefaults] boolForKey:@"ForceNonexecutableHeapForPlugins"];
+ if (forceNonexecutableHeapForPlugins)
+ return false;
+
+ if (pluginInfo.bundleIdentifier == "com.apple.QuickTime Plugin.plugin")
+ return false;
+
+ return true;
+}
+
+bool PluginProcessProxy::createPropertyListFile(const PluginModuleInfo& plugin)
+{
+ NSBundle *webKit2Bundle = [NSBundle bundleWithIdentifier:@"com.apple.WebKit2"];
+ NSString *frameworksPath = [[webKit2Bundle bundlePath] stringByDeletingLastPathComponent];
+ const char* frameworkExecutablePath = [[webKit2Bundle executablePath] fileSystemRepresentation];
+
+ NSString *processPath = [webKit2Bundle pathForAuxiliaryExecutable:@"PluginProcess.app"];
+ NSString *processAppExecutablePath = [[NSBundle bundleWithPath:processPath] executablePath];
+
+ CString pluginPathString = fileSystemRepresentation(plugin.path);
+
+ posix_spawnattr_t attr;
+ posix_spawnattr_init(&attr);
+
+ cpu_type_t cpuTypes[] = { plugin.pluginArchitecture };
+ size_t outCount = 0;
+ posix_spawnattr_setbinpref_np(&attr, 1, cpuTypes, &outCount);
+
+ EnvironmentVariables environmentVariables;
+
+ // To make engineering builds work, if the path is outside of /System set up
+ // DYLD_FRAMEWORK_PATH to pick up other frameworks, but don't do it for the
+ // production configuration because it involves extra file system access.
+ if (![frameworksPath hasPrefix:@"/System/"])
+ environmentVariables.appendValue("DYLD_FRAMEWORK_PATH", [frameworksPath fileSystemRepresentation], ':');
+
+ const char* args[] = { [processAppExecutablePath fileSystemRepresentation], frameworkExecutablePath, "-type", "pluginprocess", "-createPluginMIMETypesPreferences", pluginPathString.data(), 0 };
+
+ pid_t pid;
+ int result = posix_spawn(&pid, args[0], 0, &attr, const_cast<char* const*>(args), environmentVariables.environmentPointer());
+ posix_spawnattr_destroy(&attr);
+
+ if (result)
+ return false;
+ int status;
+ if (waitpid(pid, &status, 0) < 0)
+ return false;
+
+ if (!WIFEXITED(status))
+ return false;
+
+ if (WEXITSTATUS(status) != EXIT_SUCCESS)
+ return false;
+
+ return true;
+}
+
+void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationParameters& parameters)
+{
+#if USE(ACCELERATED_COMPOSITING) && HAVE(HOSTED_CORE_ANIMATION)
+ parameters.parentProcessName = [[NSProcessInfo processInfo] processName];
+ mach_port_t renderServerPort = WKInitializeRenderServer();
+ if (renderServerPort != MACH_PORT_NULL)
+ parameters.acceleratedCompositingPort = CoreIPC::MachPort(renderServerPort, MACH_MSG_TYPE_COPY_SEND);
+#endif
+}
+
+bool PluginProcessProxy::getPluginProcessSerialNumber(ProcessSerialNumber& pluginProcessSerialNumber)
+{
+ pid_t pluginProcessPID = m_processLauncher->processIdentifier();
+ return GetProcessForPID(pluginProcessPID, &pluginProcessSerialNumber) == noErr;
+}
+
+void PluginProcessProxy::makePluginProcessTheFrontProcess()
+{
+ ProcessSerialNumber pluginProcessSerialNumber;
+ if (!getPluginProcessSerialNumber(pluginProcessSerialNumber))
+ return;
+
+ SetFrontProcess(&pluginProcessSerialNumber);
+}
+
+void PluginProcessProxy::makeUIProcessTheFrontProcess()
+{
+ ProcessSerialNumber processSerialNumber;
+ GetCurrentProcess(&processSerialNumber);
+ SetFrontProcess(&processSerialNumber);
+}
+
+void PluginProcessProxy::setFullscreenWindowIsShowing(bool fullscreenWindowIsShowing)
+{
+ if (m_fullscreenWindowIsShowing == fullscreenWindowIsShowing)
+ return;
+
+ m_fullscreenWindowIsShowing = fullscreenWindowIsShowing;
+ if (m_fullscreenWindowIsShowing)
+ enterFullscreen();
+ else
+ exitFullscreen();
+}
+
+void PluginProcessProxy::enterFullscreen()
+{
+ // Get the current presentation options.
+ m_preFullscreenAppPresentationOptions = [NSApp presentationOptions];
+
+ // Figure out which presentation options to use.
+ unsigned presentationOptions = m_preFullscreenAppPresentationOptions & ~(NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar);
+ presentationOptions |= NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar;
+
+ [NSApp setPresentationOptions:presentationOptions];
+ makePluginProcessTheFrontProcess();
+}
+
+void PluginProcessProxy::exitFullscreen()
+{
+ // If the plug-in host is the current application then we should bring ourselves to the front when it exits full-screen mode.
+ ProcessSerialNumber frontProcessSerialNumber;
+ GetFrontProcess(&frontProcessSerialNumber);
+
+ // The UI process must be the front process in order to change the presentation mode.
+ makeUIProcessTheFrontProcess();
+ [NSApp setPresentationOptions:m_preFullscreenAppPresentationOptions];
+
+ ProcessSerialNumber pluginProcessSerialNumber;
+ if (!getPluginProcessSerialNumber(pluginProcessSerialNumber))
+ return;
+
+ // If the plug-in process was not the front process, switch back to the previous front process.
+ // (Otherwise we'll keep the UI process as the front process).
+ Boolean isPluginProcessFrontProcess;
+ SameProcess(&frontProcessSerialNumber, &pluginProcessSerialNumber, &isPluginProcessFrontProcess);
+ if (!isPluginProcessFrontProcess)
+ SetFrontProcess(&frontProcessSerialNumber);
+}
+
+void PluginProcessProxy::setModalWindowIsShowing(bool modalWindowIsShowing)
+{
+ if (modalWindowIsShowing == m_modalWindowIsShowing)
+ return;
+
+ m_modalWindowIsShowing = modalWindowIsShowing;
+
+ if (m_modalWindowIsShowing)
+ beginModal();
+ else
+ endModal();
+}
+
+void PluginProcessProxy::beginModal()
+{
+ ASSERT(!m_placeholderWindow);
+ ASSERT(!m_activationObserver);
+
+ m_placeholderWindow.adoptNS([[WKPlaceholderModalWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]);
+ [m_placeholderWindow.get() setReleasedWhenClosed:NO];
+
+ m_activationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillBecomeActiveNotification object:NSApp queue:nil
+ usingBlock:^(NSNotification *){ applicationDidBecomeActive(); }];
+
+ [NSApp runModalForWindow:m_placeholderWindow.get()];
+
+ [m_placeholderWindow.get() orderOut:nil];
+ m_placeholderWindow = nullptr;
+}
+
+void PluginProcessProxy::endModal()
+{
+ ASSERT(m_placeholderWindow);
+ ASSERT(m_activationObserver);
+
+ [[NSNotificationCenter defaultCenter] removeObserver:m_activationObserver.get()];
+ m_activationObserver = nullptr;
+
+ [NSApp stopModal];
+
+ makeUIProcessTheFrontProcess();
+}
+
+void PluginProcessProxy::applicationDidBecomeActive()
+{
+ makePluginProcessTheFrontProcess();
+}
+
+
+} // namespace WebKit
+
+#endif // ENABLE(PLUGIN_PROCESS)
diff --git a/Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp b/Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp
new file mode 100644
index 000000000..cc521e0af
--- /dev/null
+++ b/Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 Nokia 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 INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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 "PluginProcessProxy.h"
+
+#if ENABLE(PLUGIN_PROCESS)
+
+#include "PluginProcessCreationParameters.h"
+#include <WebCore/NotImplemented.h>
+
+namespace WebKit {
+
+void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationParameters& parameters)
+{
+ notImplemented();
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(PLUGIN_PROCESS)
diff --git a/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp b/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp
new file mode 100644
index 000000000..caecf7942
--- /dev/null
+++ b/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2010 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 INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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.
+ */
+
+// Note: this file is only for UNIX. On other platforms we can reuse the native implementation.
+
+#include "config.h"
+#include "PluginInfoStore.h"
+
+#include "NetscapePluginModule.h"
+#include "PluginDatabase.h"
+#include <WebCore/FileSystem.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+Vector<String> PluginInfoStore::pluginsDirectories()
+{
+ Vector<String> result;
+
+ result.append(homeDirectoryPath() + "/.mozilla/plugins");
+ result.append(homeDirectoryPath() + "/.netscape/plugins");
+ result.append("/usr/lib/browser/plugins");
+ result.append("/usr/local/lib/mozilla/plugins");
+ result.append("/usr/lib/firefox/plugins");
+ result.append("/usr/lib64/browser-plugins");
+ result.append("/usr/lib/browser-plugins");
+ result.append("/usr/lib/mozilla/plugins");
+ result.append("/usr/local/netscape/plugins");
+ result.append("/opt/mozilla/plugins");
+ result.append("/opt/mozilla/lib/plugins");
+ result.append("/opt/netscape/plugins");
+ result.append("/opt/netscape/communicator/plugins");
+ result.append("/usr/lib/netscape/plugins");
+ result.append("/usr/lib/netscape/plugins-libc5");
+ result.append("/usr/lib/netscape/plugins-libc6");
+ result.append("/usr/lib64/netscape/plugins");
+ result.append("/usr/lib64/mozilla/plugins");
+ result.append("/usr/lib/nsbrowser/plugins");
+ result.append("/usr/lib64/nsbrowser/plugins");
+
+ String mozillaHome(getenv("MOZILLA_HOME"));
+ if (!mozillaHome.isEmpty())
+ result.append(mozillaHome + "/plugins");
+
+ String mozillaPaths(getenv("MOZ_PLUGIN_PATH"));
+ if (!mozillaPaths.isEmpty()) {
+ Vector<String> paths;
+ mozillaPaths.split(UChar(':'), /* allowEmptyEntries */ false, paths);
+ result.append(paths);
+ }
+
+ return result;
+}
+
+Vector<String> PluginInfoStore::pluginPathsInDirectory(const String& directory)
+{
+ Vector<String> result;
+ Vector<String> pluginPaths = listDirectory(directory, String("*.so"));
+ Vector<String>::const_iterator end = pluginPaths.end();
+ for (Vector<String>::const_iterator it = pluginPaths.begin(); it != end; ++it) {
+ if (fileExists(*it))
+ result.append(*it);
+ }
+
+ return result;
+}
+
+Vector<String> PluginInfoStore::individualPluginPaths()
+{
+ return Vector<String>();
+}
+
+bool PluginInfoStore::getPluginInfo(const String& pluginPath, PluginModuleInfo& plugin)
+{
+ return NetscapePluginModule::getPluginInfo(pluginPath, plugin);
+}
+
+bool PluginInfoStore::shouldUsePlugin(Vector<PluginModuleInfo>& alreadyLoadedPlugins, const PluginModuleInfo& plugin)
+{
+ // We do not do any black-listing presently.
+ return true;
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp b/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp
new file mode 100644
index 000000000..78d0562d9
--- /dev/null
+++ b/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2010 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 INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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 "NetscapePluginModule.h"
+#include <WebCore/FileSystem.h>
+#include <WebCore/PathWalker.h>
+#include <shlwapi.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+static inline Vector<int> parseVersionString(const String& versionString)
+{
+ Vector<int> version;
+
+ unsigned startPos = 0;
+ unsigned endPos;
+
+ while (startPos < versionString.length()) {
+ for (endPos = startPos; endPos < versionString.length(); ++endPos)
+ if (versionString[endPos] == '.' || versionString[endPos] == '_')
+ break;
+
+ int versionComponent = versionString.substring(startPos, endPos - startPos).toInt();
+ version.append(versionComponent);
+
+ startPos = endPos + 1;
+ }
+
+ return version;
+}
+
+// This returns whether versionA is higher than versionB
+static inline bool compareVersions(const Vector<int>& versionA, const Vector<int>& versionB)
+{
+ for (unsigned i = 0; i < versionA.size(); i++) {
+ if (i >= versionB.size())
+ return true;
+
+ if (versionA[i] > versionB[i])
+ return true;
+ else if (versionA[i] < versionB[i])
+ return false;
+ }
+
+ // If we come here, the versions are either the same or versionB has an extra component, just return false
+ return false;
+}
+
+static inline String safariPluginsDirectory()
+{
+ static String pluginsDirectory;
+ static bool cachedPluginDirectory = false;
+
+ if (!cachedPluginDirectory) {
+ cachedPluginDirectory = true;
+
+ WCHAR moduleFileNameStr[MAX_PATH];
+ int moduleFileNameLen = ::GetModuleFileNameW(0, moduleFileNameStr, WTF_ARRAY_LENGTH(moduleFileNameStr));
+
+ if (!moduleFileNameLen || moduleFileNameLen == WTF_ARRAY_LENGTH(moduleFileNameStr))
+ return pluginsDirectory;
+
+ if (!::PathRemoveFileSpecW(moduleFileNameStr))
+ return pluginsDirectory;
+
+ pluginsDirectory = String(moduleFileNameStr) + "\\Plugins";
+ }
+
+ return pluginsDirectory;
+}
+
+static inline void addMozillaPluginDirectories(Vector<String>& directories)
+{
+ // Enumerate all Mozilla plugin directories in the registry
+ HKEY key;
+ LONG result = ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Mozilla", 0, KEY_READ, &key);
+ if (result != ERROR_SUCCESS)
+ return;
+
+ WCHAR name[128];
+ FILETIME lastModified;
+
+ // Enumerate subkeys
+ for (int i = 0;; i++) {
+ DWORD nameLen = WTF_ARRAY_LENGTH(name);
+ result = ::RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
+
+ if (result != ERROR_SUCCESS)
+ break;
+
+ String extensionsPath = String(name, nameLen) + "\\Extensions";
+ HKEY extensionsKey;
+
+ // Try opening the key
+ result = ::RegOpenKeyExW(key, extensionsPath.charactersWithNullTermination(), 0, KEY_READ, &extensionsKey);
+
+ if (result == ERROR_SUCCESS) {
+ // Now get the plugins directory
+ WCHAR pluginsDirectoryStr[MAX_PATH];
+ DWORD pluginsDirectorySize = sizeof(pluginsDirectoryStr);
+ DWORD type;
+
+ result = ::RegQueryValueExW(extensionsKey, L"Plugins", 0, &type, reinterpret_cast<LPBYTE>(&pluginsDirectoryStr), &pluginsDirectorySize);
+
+ if (result == ERROR_SUCCESS && type == REG_SZ)
+ directories.append(String(pluginsDirectoryStr, pluginsDirectorySize / sizeof(WCHAR) - 1));
+
+ ::RegCloseKey(extensionsKey);
+ }
+ }
+
+ ::RegCloseKey(key);
+}
+
+static inline void addWindowsMediaPlayerPluginDirectory(Vector<String>& directories)
+{
+ // The new WMP Firefox plugin is installed in \PFiles\Plugins if it can't find any Firefox installs
+ WCHAR pluginDirectoryStr[MAX_PATH + 1];
+ DWORD pluginDirectorySize = ::ExpandEnvironmentStringsW(L"%SYSTEMDRIVE%\\PFiles\\Plugins", pluginDirectoryStr, WTF_ARRAY_LENGTH(pluginDirectoryStr));
+
+ if (pluginDirectorySize > 0 && pluginDirectorySize <= WTF_ARRAY_LENGTH(pluginDirectoryStr))
+ directories.append(String(pluginDirectoryStr, pluginDirectorySize - 1));
+
+ DWORD type;
+ WCHAR installationDirectoryStr[MAX_PATH];
+ DWORD installationDirectorySize = sizeof(installationDirectoryStr);
+
+ HRESULT result = ::SHGetValueW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\MediaPlayer", L"Installation Directory", &type, reinterpret_cast<LPBYTE>(&installationDirectoryStr), &installationDirectorySize);
+
+ if (result == ERROR_SUCCESS && type == REG_SZ)
+ directories.append(String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1));
+}
+
+static inline void addQuickTimePluginDirectory(Vector<String>& directories)
+{
+ DWORD type;
+ WCHAR installationDirectoryStr[MAX_PATH];
+ DWORD installationDirectorySize = sizeof(installationDirectoryStr);
+
+ HRESULT result = ::SHGetValueW(HKEY_LOCAL_MACHINE, L"Software\\Apple Computer, Inc.\\QuickTime", L"InstallDir", &type, reinterpret_cast<LPBYTE>(&installationDirectoryStr), &installationDirectorySize);
+
+ if (result == ERROR_SUCCESS && type == REG_SZ) {
+ String pluginDir = String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1) + "\\plugins";
+ directories.append(pluginDir);
+ }
+}
+
+static inline void addAdobeAcrobatPluginDirectory(Vector<String>& directories)
+{
+ HKEY key;
+ HRESULT result = ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Adobe\\Acrobat Reader", 0, KEY_READ, &key);
+ if (result != ERROR_SUCCESS)
+ return;
+
+ WCHAR name[128];
+ FILETIME lastModified;
+
+ Vector<int> latestAcrobatVersion;
+ String latestAcrobatVersionString;
+
+ // Enumerate subkeys
+ for (int i = 0;; i++) {
+ DWORD nameLen = WTF_ARRAY_LENGTH(name);
+ result = ::RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
+
+ if (result != ERROR_SUCCESS)
+ break;
+
+ Vector<int> acrobatVersion = parseVersionString(String(name, nameLen));
+ if (compareVersions(acrobatVersion, latestAcrobatVersion)) {
+ latestAcrobatVersion = acrobatVersion;
+ latestAcrobatVersionString = String(name, nameLen);
+ }
+ }
+
+ if (!latestAcrobatVersionString.isNull()) {
+ DWORD type;
+ WCHAR acrobatInstallPathStr[MAX_PATH];
+ DWORD acrobatInstallPathSize = sizeof(acrobatInstallPathStr);
+
+ String acrobatPluginKeyPath = "Software\\Adobe\\Acrobat Reader\\" + latestAcrobatVersionString + "\\InstallPath";
+ result = ::SHGetValueW(HKEY_LOCAL_MACHINE, acrobatPluginKeyPath.charactersWithNullTermination(), 0, &type, reinterpret_cast<LPBYTE>(acrobatInstallPathStr), &acrobatInstallPathSize);
+
+ if (result == ERROR_SUCCESS) {
+ String acrobatPluginDirectory = String(acrobatInstallPathStr, acrobatInstallPathSize / sizeof(WCHAR) - 1) + "\\browser";
+ directories.append(acrobatPluginDirectory);
+ }
+ }
+
+ ::RegCloseKey(key);
+}
+
+static inline void addMacromediaPluginDirectories(Vector<String>& directories)
+{
+#if !OS(WINCE)
+ WCHAR systemDirectoryStr[MAX_PATH];
+
+ if (!::GetSystemDirectoryW(systemDirectoryStr, WTF_ARRAY_LENGTH(systemDirectoryStr)))
+ return;
+
+ WCHAR macromediaDirectoryStr[MAX_PATH];
+
+ if (!::PathCombineW(macromediaDirectoryStr, systemDirectoryStr, L"macromed\\Flash"))
+ return;
+
+ directories.append(macromediaDirectoryStr);
+
+ if (!::PathCombineW(macromediaDirectoryStr, systemDirectoryStr, L"macromed\\Shockwave 10"))
+ return;
+
+ directories.append(macromediaDirectoryStr);
+#endif
+}
+
+Vector<String> PluginInfoStore::pluginsDirectories()
+{
+ Vector<String> directories;
+
+ String ourDirectory = safariPluginsDirectory();
+ if (!ourDirectory.isNull())
+ directories.append(ourDirectory);
+
+ addQuickTimePluginDirectory(directories);
+ addAdobeAcrobatPluginDirectory(directories);
+ addMozillaPluginDirectories(directories);
+ addWindowsMediaPlayerPluginDirectory(directories);
+ addMacromediaPluginDirectories(directories);
+
+ return directories;
+}
+
+Vector<String> PluginInfoStore::pluginPathsInDirectory(const String& directory)
+{
+ Vector<String> paths;
+
+ PathWalker walker(directory, "*");
+ if (!walker.isValid())
+ return paths;
+
+ do {
+ if (walker.data().dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+
+ String filename = walker.data().cFileName;
+ if ((!filename.startsWith("np", false) || !filename.endsWith("dll", false)) && (!equalIgnoringCase(filename, "Plugin.dll") || !directory.endsWith("Shockwave 10", false)))
+ continue;
+
+ paths.append(directory + "\\" + filename);
+ } while (walker.step());
+
+ return paths;
+}
+
+static void addPluginPathsFromRegistry(HKEY rootKey, Vector<String>& paths)
+{
+ HKEY key;
+ if (::RegOpenKeyExW(rootKey, L"Software\\MozillaPlugins", 0, KEY_ENUMERATE_SUB_KEYS, &key) != ERROR_SUCCESS)
+ return;
+
+ for (size_t i = 0; ; ++i) {
+ // MSDN says that key names have a maximum length of 255 characters.
+ wchar_t name[256];
+ DWORD nameLen = WTF_ARRAY_LENGTH(name);
+ if (::RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, 0) != ERROR_SUCCESS)
+ break;
+
+ wchar_t path[MAX_PATH];
+ DWORD pathSizeInBytes = sizeof(path);
+ DWORD type;
+ if (::SHGetValueW(key, name, L"Path", &type, path, &pathSizeInBytes) != ERROR_SUCCESS)
+ continue;
+ if (type != REG_SZ)
+ continue;
+
+ paths.append(path);
+ }
+
+ ::RegCloseKey(key);
+}
+
+Vector<String> PluginInfoStore::individualPluginPaths()
+{
+ Vector<String> paths;
+
+ addPluginPathsFromRegistry(HKEY_LOCAL_MACHINE, paths);
+ addPluginPathsFromRegistry(HKEY_CURRENT_USER, paths);
+
+ return paths;
+}
+
+static uint64_t fileVersion(DWORD leastSignificant, DWORD mostSignificant)
+{
+ ULARGE_INTEGER version;
+ version.LowPart = leastSignificant;
+ version.HighPart = mostSignificant;
+ return version.QuadPart;
+}
+
+bool PluginInfoStore::getPluginInfo(const String& pluginPath, PluginModuleInfo& plugin)
+{
+ return NetscapePluginModule::getPluginInfo(pluginPath, plugin);
+}
+
+static bool isOldWindowsMediaPlayerPlugin(const PluginModuleInfo& plugin)
+{
+ return equalIgnoringCase(plugin.info.file, "npdsplay.dll");
+}
+
+static bool isNewWindowsMediaPlayerPlugin(const PluginModuleInfo& plugin)
+{
+ return equalIgnoringCase(plugin.info.file, "np-mswmp.dll");
+}
+
+bool PluginInfoStore::shouldUsePlugin(Vector<PluginModuleInfo>& alreadyLoadedPlugins, const PluginModuleInfo& plugin)
+{
+ if (plugin.info.name == "Citrix ICA Client") {
+ // The Citrix ICA Client plug-in requires a Mozilla-based browser; see <rdar://6418681>.
+ return false;
+ }
+
+ if (plugin.info.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
+ static const uint64_t minimumRequiredVersion = fileVersion(0x51BE0000, 0x00010000);
+ return plugin.fileVersion >= minimumRequiredVersion;
+ }
+
+ if (equalIgnoringCase(plugin.info.file, "npmozax.dll")) {
+ // Bug 15217: Mozilla ActiveX control complains about missing xpcom_core.dll
+ return false;
+ }
+
+ if (equalIgnoringCase(plugin.info.file, "npwpf.dll")) {
+ // Bug 57119: Microsoft Windows Presentation Foundation (WPF) plug-in complains about missing xpcom.dll
+ return false;
+ }
+
+ if (plugin.info.name == "Yahoo Application State Plugin") {
+ // https://bugs.webkit.org/show_bug.cgi?id=26860
+ // Bug in Yahoo Application State plug-in earlier than 1.0.0.6 leads to heap corruption.
+ static const uint64_t minimumRequiredVersion = fileVersion(0x00000006, 0x00010000);
+ return plugin.fileVersion >= minimumRequiredVersion;
+ }
+
+ if (isOldWindowsMediaPlayerPlugin(plugin)) {
+ // Don't load the old Windows Media Player plugin if we've already loaded the new Windows
+ // Media Player plugin.
+ for (size_t i = 0; i < alreadyLoadedPlugins.size(); ++i) {
+ if (!isNewWindowsMediaPlayerPlugin(alreadyLoadedPlugins[i]))
+ continue;
+ return false;
+ }
+ return true;
+ }
+
+ if (isNewWindowsMediaPlayerPlugin(plugin)) {
+ // Remove the old Windows Media Player plugin if we've already added it.
+ for (size_t i = 0; i < alreadyLoadedPlugins.size(); ++i) {
+ if (!isOldWindowsMediaPlayerPlugin(alreadyLoadedPlugins[i]))
+ continue;
+ alreadyLoadedPlugins.remove(i);
+ }
+ return true;
+ }
+
+ // FIXME: We should prefer a newer version of a plugin to an older version, rather than loading
+ // only the first. <http://webkit.org/b/58469>
+ String pluginFileName = pathGetFileName(plugin.path);
+ for (size_t i = 0; i < alreadyLoadedPlugins.size(); ++i) {
+ const PluginModuleInfo& loadedPlugin = alreadyLoadedPlugins[i];
+
+ // If a plug-in with the same filename already exists, we don't want to load it.
+ if (equalIgnoringCase(pluginFileName, pathGetFileName(loadedPlugin.path)))
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace WebKit