diff options
author | Ben Murdoch <benm@google.com> | 2011-05-13 16:23:25 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-05-16 11:35:02 +0100 |
commit | 65f03d4f644ce73618e5f4f50dd694b26f55ae12 (patch) | |
tree | f478babb801e720de7bfaee23443ffe029f58731 /Source/WebKit2/UIProcess/Plugins | |
parent | 47de4a2fb7262c7ebdb9cd133ad2c54c187454d0 (diff) | |
download | external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.zip external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.tar.gz external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.tar.bz2 |
Merge WebKit at r75993: Initial merge by git.
Change-Id: I602bbdc3974787a3b0450456a30a7868286921c3
Diffstat (limited to 'Source/WebKit2/UIProcess/Plugins')
12 files changed, 1444 insertions, 0 deletions
diff --git a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp new file mode 100644 index 0000000..f4fb5ad --- /dev/null +++ b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp @@ -0,0 +1,220 @@ +/* + * 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 "PluginInfoStore.h" + +#include <WebCore/KURL.h> +#include <WebCore/MIMETypeRegistry.h> +#include <algorithm> +#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, typename V, typename W> +static void addFromVector(HashSet<T, U, V>& hashSet, const W& vector) +{ + for (size_t i = 0; i < vector.size(); ++i) + hashSet.add(vector[i]); +} + +#if OS(WINDOWS) +typedef HashSet<String, CaseFoldingHash> PathHashSet; +#else +typedef HashSet<String> PathHashSet; +#endif + +void PluginInfoStore::loadPluginsIfNecessary() +{ + if (m_pluginListIsUpToDate) + return; + + m_plugins.clear(); + + 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()); + + PathHashSet::const_iterator end = uniquePluginPaths.end(); + for (PathHashSet::const_iterator it = uniquePluginPaths.begin(); it != end; ++it) + loadPlugin(*it); + + m_pluginListIsUpToDate = true; +} + +void PluginInfoStore::loadPlugin(const String& pluginPath) +{ + Plugin plugin; + + if (!getPluginInfo(pluginPath, plugin)) + return; + + if (!shouldUsePlugin(plugin)) + return; + + // Add the plug-in. + m_plugins.append(plugin); +} + +void PluginInfoStore::getPlugins(Vector<PluginInfo>& plugins) +{ + loadPluginsIfNecessary(); + + for (size_t i = 0; i < m_plugins.size(); ++i) + plugins.append(m_plugins[i].info); +} + +PluginInfoStore::Plugin PluginInfoStore::findPluginForMIMEType(const String& mimeType) +{ + ASSERT(!mimeType.isNull()); + + for (size_t i = 0; i < m_plugins.size(); ++i) { + const Plugin& 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 Plugin(); +} + +PluginInfoStore::Plugin PluginInfoStore::findPluginForExtension(const String& extension, String& mimeType) +{ + ASSERT(!extension.isNull()); + + for (size_t i = 0; i < m_plugins.size(); ++i) { + const Plugin& 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 Plugin(); +} + +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 + +PluginInfoStore::Plugin 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()) { + Plugin 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()) { + Plugin 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()) { + Plugin plugin = findPluginForMIMEType(extensionMimeType); + if (!plugin.path.isNull()) { + mimeType = extensionMimeType; + return plugin; + } + } + } + + return Plugin(); +} + +PluginInfoStore::Plugin PluginInfoStore::infoForPluginWithPath(const String& pluginPath) +{ + for (size_t i = 0; i < m_plugins.size(); ++i) { + if (m_plugins[i].path == pluginPath) + return m_plugins[i]; + } + + ASSERT_NOT_REACHED(); + return Plugin(); +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h new file mode 100644 index 0000000..b342203 --- /dev/null +++ b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h @@ -0,0 +1,94 @@ +/* + * 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 <WebCore/PluginData.h> + +namespace WebCore { + class KURL; +} + +namespace WebKit { + +class PluginInfoStore { +public: + PluginInfoStore(); + + void setAdditionalPluginsDirectories(const Vector<String>&); + + void refresh(); + void getPlugins(Vector<WebCore::PluginInfo>& plugins); + + // Represents a single plug-in. + struct Plugin { + String path; + WebCore::PluginInfo info; +#if PLATFORM(MAC) + cpu_type_t pluginArchitecture; + String bundleIdentifier; + unsigned versionNumber; +#elif PLATFORM(WIN) + uint64_t fileVersion; +#endif + }; + + // 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. + Plugin findPlugin(String& mimeType, const WebCore::KURL& url); + + // Returns the info for the plug-in with the given path. + Plugin infoForPluginWithPath(const String& pluginPath); + +private: + + Plugin findPluginForMIMEType(const String& mimeType); + Plugin findPluginForExtension(const String& extension, String& mimeType); + + void loadPluginsIfNecessary(); + void loadPlugin(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(); + static bool getPluginInfo(const String& pluginPath, Plugin& plugin); + bool shouldUsePlugin(const Plugin& plugin); + static String getMIMETypeForExtension(const String& extension); + + Vector<String> m_additionalPluginsDirectories; + Vector<Plugin> 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 0000000..ff44e25 --- /dev/null +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp @@ -0,0 +1,81 @@ +/* + * 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) + +#include "PluginProcessManager.h" + +#include "PluginInfoStore.h" +#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 String& pluginPath, WebProcessProxy* webProcessProxy, CoreIPC::ArgumentEncoder* reply) +{ + ASSERT(!pluginPath.isNull()); + + PluginInfoStore::Plugin plugin = webProcessProxy->context()->pluginInfoStore()->infoForPluginWithPath(pluginPath); + + PluginProcessProxy* pluginProcess = 0; + + for (size_t i = 0; i < m_pluginProcesses.size(); ++i) { + if (m_pluginProcesses[i]->pluginInfo().path == plugin.path) { + pluginProcess = m_pluginProcesses[i]; + break; + } + } + + if (!pluginProcess) { + pluginProcess = PluginProcessProxy::create(this, plugin).leakPtr(); + m_pluginProcesses.append(pluginProcess); + } + + pluginProcess->createWebProcessConnection(webProcessProxy, reply); +} + +void PluginProcessManager::removePluginProcessProxy(PluginProcessProxy* pluginProcessProxy) +{ + size_t vectorIndex = m_pluginProcesses.find(pluginProcessProxy); + ASSERT(vectorIndex != notFound); + + m_pluginProcesses.remove(vectorIndex); +} + +} // 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 0000000..c265f2e --- /dev/null +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h @@ -0,0 +1,61 @@ +/* + * 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 <wtf/Forward.h> +#include <wtf/Noncopyable.h> +#include <wtf/Vector.h> + +namespace CoreIPC { + class ArgumentEncoder; +} + +namespace WebKit { + +class PluginProcessProxy; +class WebProcessProxy; + +class PluginProcessManager : Noncopyable { +public: + static PluginProcessManager& shared(); + + void getPluginProcessConnection(const String& pluginPath, WebProcessProxy*, CoreIPC::ArgumentEncoder* reply); + void removePluginProcessProxy(PluginProcessProxy*); + +private: + PluginProcessManager(); + + 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 0000000..093a31f --- /dev/null +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp @@ -0,0 +1,154 @@ +/* + * 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) + +#include "PluginProcessProxy.h" + +#include "MachPort.h" +#include "PluginProcessCreationParameters.h" +#include "PluginProcessManager.h" +#include "PluginProcessMessages.h" +#include "RunLoop.h" +#include "WebCoreArgumentCoders.h" +#include "WebProcessProxy.h" + +namespace WebKit { + +PassOwnPtr<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginInfoStore::Plugin& pluginInfo) +{ + return adoptPtr(new PluginProcessProxy(PluginProcessManager, pluginInfo)); +} + +PluginProcessProxy::PluginProcessProxy(PluginProcessManager* PluginProcessManager, const PluginInfoStore::Plugin& pluginInfo) + : m_pluginProcessManager(PluginProcessManager) + , m_pluginInfo(pluginInfo) + , m_numPendingConnectionRequests(0) +{ + ProcessLauncher::LaunchOptions launchOptions; + launchOptions.processType = ProcessLauncher::PluginProcess; +#if PLATFORM(MAC) + launchOptions.architecture = pluginInfo.pluginArchitecture; +#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::createWebProcessConnection(WebProcessProxy* webProcessProxy, CoreIPC::ArgumentEncoder* reply) +{ + m_pendingConnectionReplies.append(make_pair(webProcessProxy, reply)); + + if (m_processLauncher->isLaunching()) { + m_numPendingConnectionRequests++; + return; + } + + // Ask the plug-in process to create a connection. + m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0); +} + +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<WebProcessProxy> replyWebProcessProxy = m_pendingConnectionReplies.first().first.release(); + CoreIPC::ArgumentEncoder* reply = m_pendingConnectionReplies.first().second; + m_pendingConnectionReplies.removeFirst(); + + // FIXME: This is Mac specific. + reply->encode(CoreIPC::MachPort(0, MACH_MSG_TYPE_MOVE_SEND)); + replyWebProcessProxy->connection()->sendSyncReply(reply); + } + + // 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*) +{ + pluginProcessCrashedOrFailedToLaunch(); +} + +void PluginProcessProxy::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID) +{ +} + +void PluginProcessProxy::didFinishLaunching(ProcessLauncher*, CoreIPC::Connection::Identifier connectionIdentifier) +{ + ASSERT(!m_connection); + + if (!connectionIdentifier) { + pluginProcessCrashedOrFailedToLaunch(); + return; + } + + m_connection = CoreIPC::Connection::createServerConnection(connectionIdentifier, this, RunLoop::main()); + m_connection->open(); + + PluginProcessCreationParameters parameters; + + parameters.pluginPath = m_pluginInfo.path; + + platformInitializePluginProcess(parameters); + + // Initialize the plug-in host process. + m_connection->send(Messages::PluginProcess::Initialize(parameters), 0); + + // Send all our pending requests. + for (unsigned i = 0; i < m_numPendingConnectionRequests; ++i) + m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0); + + m_numPendingConnectionRequests = 0; +} + +void PluginProcessProxy::didCreateWebProcessConnection(const CoreIPC::MachPort& machPort) +{ + ASSERT(!m_pendingConnectionReplies.isEmpty()); + + // Grab the first pending connection reply. + RefPtr<WebProcessProxy> replyWebProcessProxy = m_pendingConnectionReplies.first().first.release(); + CoreIPC::ArgumentEncoder* reply = m_pendingConnectionReplies.first().second; + m_pendingConnectionReplies.removeFirst(); + + // FIXME: This is Mac specific. + reply->encode(CoreIPC::MachPort(machPort.port(), MACH_MSG_TYPE_MOVE_SEND)); + replyWebProcessProxy->connection()->sendSyncReply(reply); +} + +} // 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 0000000..23a6df0 --- /dev/null +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h @@ -0,0 +1,101 @@ +/* + * 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 "PluginInfoStore.h" +#include "ProcessLauncher.h" +#include <wtf/Deque.h> + +// FIXME: This is platform specific. +namespace CoreIPC { + class MachPort; +} + +namespace WebKit { + +class PluginProcessManager; +class WebProcessProxy; +struct PluginProcessCreationParameters; + +class PluginProcessProxy : CoreIPC::Connection::Client, ProcessLauncher::Client { +public: + static PassOwnPtr<PluginProcessProxy> create(PluginProcessManager*, const PluginInfoStore::Plugin&); + ~PluginProcessProxy(); + + const PluginInfoStore::Plugin& 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 createWebProcessConnection(WebProcessProxy*, CoreIPC::ArgumentEncoder* reply); + +private: + PluginProcessProxy(PluginProcessManager*, const PluginInfoStore::Plugin&); + + 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); + + // ProcessLauncher::Client + virtual void didFinishLaunching(ProcessLauncher*, CoreIPC::Connection::Identifier); + + // Message handlers + void didReceivePluginProcessProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); + void didCreateWebProcessConnection(const CoreIPC::MachPort&); + + void platformInitializePluginProcess(PluginProcessCreationParameters& parameters); + + // The plug-in host process manager. + PluginProcessManager* m_pluginProcessManager; + + // Information about the plug-in. + PluginInfoStore::Plugin 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<std::pair<RefPtr<WebProcessProxy>, CoreIPC::ArgumentEncoder*> > m_pendingConnectionReplies; + + // 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; + +}; + +} // 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 0000000..cbd5abc --- /dev/null +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in @@ -0,0 +1,30 @@ +# 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 { + # FIXME: This is platform specific + DidCreateWebProcessConnection(CoreIPC::MachPort connectionIdentifier) +} + +#endif diff --git a/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoStoreGtk.cpp b/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoStoreGtk.cpp new file mode 100644 index 0000000..8a6e86c --- /dev/null +++ b/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoStoreGtk.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Portions Copyright (c) 2010 Motorola Mobility, 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 "PluginInfoStore.h" + +#include "NotImplemented.h" +#include "PluginDatabase.h" +#include "PluginPackage.h" + +using namespace WebCore; + +namespace WebKit { + +Vector<String> PluginInfoStore::pluginsDirectories() +{ + notImplemented(); + return Vector<String>(); +} + +Vector<String> PluginInfoStore::pluginPathsInDirectory(const String& directory) +{ + notImplemented(); + return Vector<String>(); +} + +Vector<String> PluginInfoStore::individualPluginPaths() +{ + return Vector<String>(); +} + +bool PluginInfoStore::getPluginInfo(const String& pluginPath, Plugin& plugin) +{ + notImplemented(); + return false; +} + +bool PluginInfoStore::shouldUsePlugin(const Plugin& plugin) +{ + notImplemented(); + return false; +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/mac/PluginInfoStoreMac.mm b/Source/WebKit2/UIProcess/Plugins/mac/PluginInfoStoreMac.mm new file mode 100644 index 0000000..b787101 --- /dev/null +++ b/Source/WebKit2/UIProcess/Plugins/mac/PluginInfoStoreMac.mm @@ -0,0 +1,101 @@ +/* + * 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 "PluginInfoStore.h" + +#include "NetscapePluginModule.h" +#include "WebKitSystemInterface.h" +#include <WebCore/WebCoreNSStringExtras.h> +#include <wtf/HashSet.h> +#include <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, Plugin& plugin) +{ + return NetscapePluginModule::getPluginInfo(pluginPath, plugin); +} + +bool PluginInfoStore::shouldUsePlugin(const Plugin& plugin) +{ + for (size_t i = 0; i < m_plugins.size(); ++i) { + const Plugin& loadedPlugin = m_plugins[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 0000000..81c8620 --- /dev/null +++ b/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm @@ -0,0 +1,46 @@ +/* + * 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) + +#include "PluginProcessProxy.h" + +#include "PluginProcessCreationParameters.h" +#include "WebKitSystemInterface.h" + +namespace WebKit { + +void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationParameters& parameters) +{ +#if USE(ACCELERATED_COMPOSITING) && HAVE(HOSTED_CORE_ANIMATION) + mach_port_t renderServerPort = WKInitializeRenderServer(); + if (renderServerPort != MACH_PORT_NULL) + parameters.acceleratedCompositingPort = CoreIPC::MachPort(renderServerPort, MACH_MSG_TYPE_COPY_SEND); +#endif +} + +} // namespace WebKit + +#endif // ENABLE(PLUGIN_PROCESS) diff --git a/Source/WebKit2/UIProcess/Plugins/qt/PluginInfoStoreQt.cpp b/Source/WebKit2/UIProcess/Plugins/qt/PluginInfoStoreQt.cpp new file mode 100644 index 0000000..fc77663 --- /dev/null +++ b/Source/WebKit2/UIProcess/Plugins/qt/PluginInfoStoreQt.cpp @@ -0,0 +1,72 @@ +/* + * 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 "PluginInfoStore.h" + +#include "NetscapePluginModule.h" +#include "PluginDatabase.h" +#include "PluginPackage.h" + +using namespace WebCore; + +namespace WebKit { + +Vector<String> PluginInfoStore::pluginsDirectories() +{ + return PluginDatabase::defaultPluginDirectories(); +} + +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, Plugin& plugin) +{ + return NetscapePluginModule::getPluginInfo(pluginPath, plugin); +} + +bool PluginInfoStore::shouldUsePlugin(const Plugin& 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 0000000..485f892 --- /dev/null +++ b/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp @@ -0,0 +1,417 @@ +/* + * 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 "PluginInfoStore.h" + +#include "NetscapePluginModule.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; +} + +class PathWalker : public Noncopyable { +public: + PathWalker(const String& directory) + { + String pattern = directory + "\\*"; + m_handle = ::FindFirstFileW(pattern.charactersWithNullTermination(), &m_data); + } + + ~PathWalker() + { + if (!isValid()) + return; + ::FindClose(m_handle); + } + + bool isValid() const { return m_handle != INVALID_HANDLE_VALUE; } + const WIN32_FIND_DATAW& data() const { return m_data; } + + bool step() { return ::FindNextFileW(m_handle, &m_data); } + +private: + HANDLE m_handle; + WIN32_FIND_DATAW m_data; +}; + +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, Plugin& plugin) +{ + return NetscapePluginModule::getPluginInfo(pluginPath, plugin); +} + +static bool isOldWindowsMediaPlayerPlugin(const PluginInfoStore::Plugin& plugin) +{ + return equalIgnoringCase(plugin.info.file, "npdsplay.dll"); +} + +static bool isNewWindowsMediaPlayerPlugin(const PluginInfoStore::Plugin& plugin) +{ + return equalIgnoringCase(plugin.info.file, "np-mswmp.dll"); +} + +bool PluginInfoStore::shouldUsePlugin(const Plugin& plugin) +{ + // FIXME: We should prefer a newer version of a plugin to an older version, rather than loading + // both. <http://webkit.org/b/49075> + + 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 (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 < m_plugins.size(); ++i) { + if (!isNewWindowsMediaPlayerPlugin(m_plugins[i])) + continue; + return false; + } + return true; + } + + if (isNewWindowsMediaPlayerPlugin(plugin)) { + // Unload the old Windows Media Player plugin if we've already loaded it. + for (size_t i = 0; i < m_plugins.size(); ++i) { + if (!isOldWindowsMediaPlayerPlugin(m_plugins[i])) + continue; + m_plugins.remove(i); + } + return true; + } + + return true; +} + +} // namespace WebKit |