diff options
Diffstat (limited to 'Source/WebKit2/UIProcess/Plugins')
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 |