diff options
Diffstat (limited to 'Source/WebKit2/UIProcess/Plugins')
18 files changed, 658 insertions, 655 deletions
diff --git a/Source/WebKit2/UIProcess/Plugins/PlugInAutoStartProvider.cpp b/Source/WebKit2/UIProcess/Plugins/PlugInAutoStartProvider.cpp new file mode 100644 index 000000000..fd0e1d9ee --- /dev/null +++ b/Source/WebKit2/UIProcess/Plugins/PlugInAutoStartProvider.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2012, 2013 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 "PlugInAutoStartProvider.h" + +#include "ImmutableArray.h" +#include "ImmutableDictionary.h" +#include "WebContext.h" +#include "WebContextClient.h" +#include "WebProcessMessages.h" +#include <wtf/CurrentTime.h> + +using namespace WebCore; + +static const double plugInAutoStartExpirationTimeThreshold = 30 * 24 * 60 * 60; + +namespace WebKit { + +PlugInAutoStartProvider::PlugInAutoStartProvider(WebContext* context) + : m_context(context) +{ +} + +static double expirationTimeFromNow() +{ + return currentTime() + plugInAutoStartExpirationTimeThreshold; +} + +void PlugInAutoStartProvider::addAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash) +{ + if (m_hashToOriginMap.contains(plugInOriginHash)) + return; + + AutoStartTable::iterator it = m_autoStartTable.find(pageOrigin); + if (it == m_autoStartTable.end()) + it = m_autoStartTable.add(pageOrigin, PlugInAutoStartOriginHash()).iterator; + + double expirationTime = expirationTimeFromNow(); + it->value.set(plugInOriginHash, expirationTime); + m_hashToOriginMap.set(plugInOriginHash, pageOrigin); + + m_context->sendToAllProcesses(Messages::WebProcess::DidAddPlugInAutoStartOriginHash(plugInOriginHash, expirationTime)); + m_context->client().plugInAutoStartOriginHashesChanged(m_context); +} + +PlugInAutoStartOriginHash PlugInAutoStartProvider::autoStartOriginHashesCopy() const +{ + PlugInAutoStartOriginHash copyMap; + AutoStartTable::const_iterator end = m_autoStartTable.end(); + for (AutoStartTable::const_iterator it = m_autoStartTable.begin(); it != end; ++it) { + PlugInAutoStartOriginHash::const_iterator mapEnd = it->value.end(); + for (PlugInAutoStartOriginHash::const_iterator mapIt = it->value.begin(); mapIt != mapEnd; ++mapIt) + copyMap.set(mapIt->key, mapIt->value); + } + return copyMap; +} + +PassRefPtr<ImmutableDictionary> PlugInAutoStartProvider::autoStartOriginsTableCopy() const +{ + ImmutableDictionary::MapType map; + AutoStartTable::const_iterator end = m_autoStartTable.end(); + double now = currentTime(); + for (AutoStartTable::const_iterator it = m_autoStartTable.begin(); it != end; ++it) { + ImmutableDictionary::MapType hashMap; + PlugInAutoStartOriginHash::const_iterator valueEnd = it->value.end(); + for (PlugInAutoStartOriginHash::const_iterator valueIt = it->value.begin(); valueIt != valueEnd; ++valueIt) { + if (now > valueIt->value) + continue; + hashMap.set(String::number(valueIt->key), WebDouble::create(valueIt->value)); + } + + if (hashMap.size()) + map.set(it->key, ImmutableDictionary::adopt(hashMap)); + } + + return ImmutableDictionary::adopt(map); +} + +void PlugInAutoStartProvider::setAutoStartOriginsTable(ImmutableDictionary& table) +{ + m_hashToOriginMap.clear(); + m_autoStartTable.clear(); + HashMap<unsigned, double> hashMap; + + ImmutableDictionary::MapType::const_iterator end = table.map().end(); + for (ImmutableDictionary::MapType::const_iterator it = table.map().begin(); it != end; ++it) { + PlugInAutoStartOriginHash hashes; + ImmutableDictionary* hashesForPage = static_cast<ImmutableDictionary*>(it->value.get()); + ImmutableDictionary::MapType::const_iterator hashEnd = hashesForPage->map().end(); + for (ImmutableDictionary::MapType::const_iterator hashIt = hashesForPage->map().begin(); hashIt != hashEnd; ++hashIt) { + bool ok; + unsigned hash = hashIt->key.toUInt(&ok); + if (!ok) + continue; + + if (hashIt->value->type() != WebDouble::APIType) + continue; + + double expirationTime = static_cast<WebDouble*>(hashIt->value.get())->value(); + hashes.set(hash, expirationTime); + hashMap.set(hash, expirationTime); + m_hashToOriginMap.set(hash, it->key); + } + + m_autoStartTable.set(it->key, hashes); + } + + m_context->sendToAllProcesses(Messages::WebProcess::ResetPlugInAutoStartOriginHashes(hashMap)); +} + +void PlugInAutoStartProvider::setAutoStartOriginsArray(ImmutableArray& originList) +{ + m_autoStartOrigins.clear(); + for (size_t i = 0, length = originList.size(); i < length; ++i) { + if (originList.at(i)->type() != WebString::APIType) + continue; + m_autoStartOrigins.append(static_cast<WebString*>(originList.at(i))->string()); + } +} + +void PlugInAutoStartProvider::didReceiveUserInteraction(unsigned plugInOriginHash) +{ + HashMap<unsigned, String>::const_iterator it = m_hashToOriginMap.find(plugInOriginHash); + if (it == m_hashToOriginMap.end()) { + ASSERT_NOT_REACHED(); + return; + } + + double newExpirationTime = expirationTimeFromNow(); + m_autoStartTable.find(it->value)->value.set(plugInOriginHash, newExpirationTime); + m_context->sendToAllProcesses(Messages::WebProcess::DidAddPlugInAutoStartOriginHash(plugInOriginHash, newExpirationTime)); + m_context->client().plugInAutoStartOriginHashesChanged(m_context); +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/PlugInAutoStartProvider.h b/Source/WebKit2/UIProcess/Plugins/PlugInAutoStartProvider.h new file mode 100644 index 000000000..87c81fe3a --- /dev/null +++ b/Source/WebKit2/UIProcess/Plugins/PlugInAutoStartProvider.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2012 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 PlugInAutoStartProvider_h +#define PlugInAutoStartProvider_h + +#include <wtf/HashMap.h> +#include <wtf/HashSet.h> +#include <wtf/Noncopyable.h> +#include <wtf/Vector.h> +#include <wtf/text/StringHash.h> +#include <wtf/text/WTFString.h> + +namespace WebKit { + +class ImmutableArray; +class ImmutableDictionary; +class WebContext; + +typedef HashMap<unsigned, double> PlugInAutoStartOriginHash; +typedef Vector<String> PlugInAutoStartOrigins; + +class PlugInAutoStartProvider { + WTF_MAKE_NONCOPYABLE(PlugInAutoStartProvider); +public: + explicit PlugInAutoStartProvider(WebContext*); + + void addAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash); + void didReceiveUserInteraction(unsigned plugInOriginHash); + + PassRefPtr<ImmutableDictionary> autoStartOriginsTableCopy() const; + void setAutoStartOriginsTable(ImmutableDictionary&); + void setAutoStartOriginsArray(ImmutableArray&); + + PlugInAutoStartOriginHash autoStartOriginHashesCopy() const; + const PlugInAutoStartOrigins& autoStartOrigins() const { return m_autoStartOrigins; } + +private: + WebContext* m_context; + + typedef HashMap<String, PlugInAutoStartOriginHash, CaseFoldingHash> AutoStartTable; + AutoStartTable m_autoStartTable; + + HashMap<unsigned, String> m_hashToOriginMap; + + PlugInAutoStartOrigins m_autoStartOrigins; +}; + +} // namespace WebKit + +#endif /* PlugInAutoStartProvider_h */ diff --git a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp index 95f589b5f..ae95a0b68 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp +++ b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp @@ -35,13 +35,13 @@ #include <wtf/ListHashSet.h> #include <wtf/StdLibExtras.h> -using namespace std; using namespace WebCore; namespace WebKit { PluginInfoStore::PluginInfoStore() : m_pluginListIsUpToDate(false) + , m_client(0) { } @@ -71,16 +71,6 @@ typedef ListHashSet<String, 32, CaseFoldingHash> PathHashSet; typedef ListHashSet<String, 32> PathHashSet; #endif -static inline Vector<PluginModuleInfo> deepIsolatedCopyPluginInfoVector(const Vector<PluginModuleInfo>& vector) -{ - // Let the copy begin! - Vector<PluginModuleInfo> copy; - copy.reserveCapacity(vector.size()); - for (unsigned i = 0; i < vector.size(); ++i) - copy.append(vector[i].isolatedCopy()); - return copy; -} - void PluginInfoStore::loadPluginsIfNecessary() { if (m_pluginListIsUpToDate) @@ -100,15 +90,16 @@ void PluginInfoStore::loadPluginsIfNecessary() // Then load plug-ins that are not in the standard plug-ins directories. addFromVector(uniquePluginPaths, individualPluginPaths()); - Vector<PluginModuleInfo> plugins; + m_plugins.clear(); PathHashSet::const_iterator end = uniquePluginPaths.end(); for (PathHashSet::const_iterator it = uniquePluginPaths.begin(); it != end; ++it) - loadPlugin(plugins, *it); - - m_plugins = deepIsolatedCopyPluginInfoVector(plugins); + loadPlugin(m_plugins, *it); m_pluginListIsUpToDate = true; + + if (m_client) + m_client->pluginInfoStoreDidLoadPlugins(this); } void PluginInfoStore::loadPlugin(Vector<PluginModuleInfo>& plugins, const String& pluginPath) @@ -126,19 +117,19 @@ void PluginInfoStore::loadPlugin(Vector<PluginModuleInfo>& plugins, const String Vector<PluginModuleInfo> PluginInfoStore::plugins() { - MutexLocker locker(m_pluginsLock); loadPluginsIfNecessary(); - return deepIsolatedCopyPluginInfoVector(m_plugins); + return m_plugins; } -PluginModuleInfo PluginInfoStore::findPluginForMIMEType(const String& mimeType) const +PluginModuleInfo PluginInfoStore::findPluginForMIMEType(const String& mimeType, PluginData::AllowedPluginTypes allowedPluginTypes) const { - MutexLocker locker(m_pluginsLock); - ASSERT(!mimeType.isNull()); for (size_t i = 0; i < m_plugins.size(); ++i) { const PluginModuleInfo& plugin = m_plugins[i]; + + if (allowedPluginTypes == PluginData::OnlyApplicationPlugins && !plugin.info.isApplicationPlugin) + continue; for (size_t j = 0; j < plugin.info.mimes.size(); ++j) { const MimeClassInfo& mimeClassInfo = plugin.info.mimes[j]; @@ -150,21 +141,22 @@ PluginModuleInfo PluginInfoStore::findPluginForMIMEType(const String& mimeType) return PluginModuleInfo(); } -PluginModuleInfo PluginInfoStore::findPluginForExtension(const String& extension, String& mimeType) const +PluginModuleInfo PluginInfoStore::findPluginForExtension(const String& extension, String& mimeType, PluginData::AllowedPluginTypes allowedPluginTypes) const { - MutexLocker locker(m_pluginsLock); - ASSERT(!extension.isNull()); for (size_t i = 0; i < m_plugins.size(); ++i) { const PluginModuleInfo& plugin = m_plugins[i]; - + + if (allowedPluginTypes == PluginData::OnlyApplicationPlugins && !plugin.info.isApplicationPlugin) + continue; + 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()) { + if (std::find(extensions.begin(), extensions.end(), extension) != extensions.end()) { // We found a supported extension, set the correct MIME type. mimeType = mimeClassInfo.type; return plugin; @@ -189,32 +181,31 @@ static inline String pathExtension(const KURL& url) } #if !PLATFORM(MAC) -PluginModuleLoadPolicy PluginInfoStore::policyForPlugin(const PluginModuleInfo&) +PluginModuleLoadPolicy PluginInfoStore::defaultLoadPolicyForPlugin(const PluginModuleInfo&) { return PluginModuleLoadNormally; } -bool PluginInfoStore::reactivateInactivePlugin(const PluginModuleInfo&) -{ - return false; -} - String PluginInfoStore::getMIMETypeForExtension(const String& extension) { return MIMETypeRegistry::getMIMETypeForExtension(extension); } + +PluginModuleInfo PluginInfoStore::findPluginWithBundleIdentifier(const String&) +{ + ASSERT_NOT_REACHED(); + return PluginModuleInfo(); +} + #endif -PluginModuleInfo PluginInfoStore::findPlugin(String& mimeType, const KURL& url) +PluginModuleInfo PluginInfoStore::findPlugin(String& mimeType, const KURL& url, PluginData::AllowedPluginTypes allowedPluginTypes) { - { - MutexLocker locker(m_pluginsLock); - loadPluginsIfNecessary(); - } + loadPluginsIfNecessary(); // First, check if we can get the plug-in based on its MIME type. if (!mimeType.isNull()) { - PluginModuleInfo plugin = findPluginForMIMEType(mimeType); + PluginModuleInfo plugin = findPluginForMIMEType(mimeType, allowedPluginTypes); if (!plugin.path.isNull()) return plugin; } @@ -222,14 +213,14 @@ PluginModuleInfo PluginInfoStore::findPlugin(String& mimeType, const KURL& url) // 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); + PluginModuleInfo plugin = findPluginForExtension(extension, mimeType, allowedPluginTypes); 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); + PluginModuleInfo plugin = findPluginForMIMEType(extensionMimeType, allowedPluginTypes); if (!plugin.path.isNull()) { mimeType = extensionMimeType; return plugin; @@ -242,8 +233,6 @@ PluginModuleInfo PluginInfoStore::findPlugin(String& mimeType, const KURL& url) PluginModuleInfo PluginInfoStore::infoForPluginWithPath(const String& pluginPath) const { - MutexLocker locker(m_pluginsLock); - for (size_t i = 0; i < m_plugins.size(); ++i) { if (m_plugins[i].path == pluginPath) return m_plugins[i]; diff --git a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h index 9a6bd9f5c..c49cea7b9 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h +++ b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h @@ -29,7 +29,8 @@ #if ENABLE(NETSCAPE_PLUGIN_API) #include "PluginModuleInfo.h" -#include <wtf/ThreadingPrimitives.h> + +#include <WebCore/PluginData.h> namespace WebCore { class KURL; @@ -37,6 +38,17 @@ namespace WebCore { namespace WebKit { +class PluginInfoStore; + +class PluginInfoStoreClient { + WTF_MAKE_NONCOPYABLE(PluginInfoStoreClient); +public: + virtual ~PluginInfoStoreClient() { } + virtual void pluginInfoStoreDidLoadPlugins(PluginInfoStore*) = 0; +protected: + PluginInfoStoreClient() { } +}; + class PluginInfoStore { WTF_MAKE_NONCOPYABLE(PluginInfoStore); @@ -51,17 +63,22 @@ public: // 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&); - + PluginModuleInfo findPlugin(String& mimeType, const WebCore::KURL&, WebCore::PluginData::AllowedPluginTypes = WebCore::PluginData::AllPlugins); + + // Returns the info for the plug-in with the given bundle identifier. + PluginModuleInfo findPluginWithBundleIdentifier(const String& bundleIdentifier); + // Returns the info for the plug-in with the given path. PluginModuleInfo infoForPluginWithPath(const String& pluginPath) const; - static PluginModuleLoadPolicy policyForPlugin(const PluginModuleInfo&); - static bool reactivateInactivePlugin(const PluginModuleInfo&); + static PluginModuleLoadPolicy defaultLoadPolicyForPlugin(const PluginModuleInfo&); + + void setClient(PluginInfoStoreClient* client) { m_client = client; } + PluginInfoStoreClient* client() const { return m_client; } private: - PluginModuleInfo findPluginForMIMEType(const String& mimeType) const; - PluginModuleInfo findPluginForExtension(const String& extension, String& mimeType) const; + PluginModuleInfo findPluginForMIMEType(const String& mimeType, WebCore::PluginData::AllowedPluginTypes) const; + PluginModuleInfo findPluginForExtension(const String& extension, String& mimeType, WebCore::PluginData::AllowedPluginTypes) const; void loadPluginsIfNecessary(); static void loadPlugin(Vector<PluginModuleInfo>& plugins, const String& pluginPath); @@ -89,8 +106,7 @@ private: Vector<String> m_additionalPluginsDirectories; Vector<PluginModuleInfo> m_plugins; bool m_pluginListIsUpToDate; - - mutable Mutex m_pluginsLock; + PluginInfoStoreClient* m_client; }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp index 834c87fc4..2279aaecd 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp @@ -30,6 +30,7 @@ #include "PluginProcessProxy.h" #include "WebContext.h" +#include <wtf/CryptographicallyRandomNumber.h> #include <wtf/StdLibExtras.h> #include <wtf/text/WTFString.h> @@ -45,12 +46,42 @@ PluginProcessManager::PluginProcessManager() { } -void PluginProcessManager::getPluginProcessConnection(const PluginInfoStore& pluginInfoStore, const String& pluginPath, PluginProcess::Type processType, PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply) +uint64_t PluginProcessManager::pluginProcessToken(const PluginModuleInfo& pluginModuleInfo, PluginProcessType pluginProcessType, PluginProcessSandboxPolicy pluginProcessSandboxPolicy) { - ASSERT(!pluginPath.isNull()); + // See if we know this token already. + for (size_t i = 0; i < m_pluginProcessTokens.size(); ++i) { + const PluginProcessAttributes& attributes = m_pluginProcessTokens[i].first; + + if (attributes.moduleInfo.path == pluginModuleInfo.path + && attributes.processType == pluginProcessType + && attributes.sandboxPolicy == pluginProcessSandboxPolicy) + return m_pluginProcessTokens[i].second; + } + + uint64_t token; + while (true) { + cryptographicallyRandomValues(&token, sizeof(token)); + + if (m_knownTokens.isValidValue(token) && !m_knownTokens.contains(token)) + break; + } + + PluginProcessAttributes attributes; + attributes.moduleInfo = pluginModuleInfo; + attributes.processType = pluginProcessType; + attributes.sandboxPolicy = pluginProcessSandboxPolicy; + + m_pluginProcessTokens.append(std::make_pair(std::move(attributes), token)); + m_knownTokens.add(token); + + return token; +} - PluginModuleInfo plugin = pluginInfoStore.infoForPluginWithPath(pluginPath); - PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(plugin, processType); +void PluginProcessManager::getPluginProcessConnection(uint64_t pluginProcessToken, PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply) +{ + ASSERT(pluginProcessToken); + + PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(pluginProcessToken); pluginProcess->getPluginProcessConnection(reply); } @@ -64,38 +95,35 @@ void PluginProcessManager::removePluginProcessProxy(PluginProcessProxy* pluginPr void PluginProcessManager::getSitesWithData(const PluginModuleInfo& plugin, WebPluginSiteDataManager* webPluginSiteDataManager, uint64_t callbackID) { - PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(plugin, PluginProcess::TypeRegularProcess); + PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(pluginProcessToken(plugin, PluginProcessTypeNormal, PluginProcessSandboxPolicyNormal)); 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::TypeRegularProcess); + PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(pluginProcessToken(plugin, PluginProcessTypeNormal, PluginProcessSandboxPolicyNormal)); pluginProcess->clearSiteData(webPluginSiteDataManager, sites, flags, maxAgeInSeconds, callbackID); } -PluginProcessProxy* PluginProcessManager::pluginProcessWithPath(const String& pluginPath, PluginProcess::Type processType) +PluginProcessProxy* PluginProcessManager::getOrCreatePluginProcess(uint64_t pluginProcessToken) { for (size_t i = 0; i < m_pluginProcesses.size(); ++i) { - RefPtr<PluginProcessProxy>& pluginProcessProxy = m_pluginProcesses[i]; - if (pluginProcessProxy->pluginInfo().path == pluginPath && pluginProcessProxy->processType() == processType) - return pluginProcessProxy.get(); + if (m_pluginProcesses[i]->pluginProcessToken() == pluginProcessToken) + return m_pluginProcesses[i].get(); } - return 0; -} + for (size_t i = 0; i < m_pluginProcessTokens.size(); ++i) { + auto& attributesAndToken = m_pluginProcessTokens[i]; + if (attributesAndToken.second == pluginProcessToken) { + RefPtr<PluginProcessProxy> pluginProcess = PluginProcessProxy::create(this, attributesAndToken.first, attributesAndToken.second); + PluginProcessProxy* pluginProcessPtr = pluginProcess.get(); -PluginProcessProxy* PluginProcessManager::getOrCreatePluginProcess(const PluginModuleInfo& plugin, PluginProcess::Type processType) -{ - if (PluginProcessProxy* pluginProcess = pluginProcessWithPath(plugin.path, processType)) - return pluginProcess; - - RefPtr<PluginProcessProxy> pluginProcess = PluginProcessProxy::create(this, plugin, processType); - PluginProcessProxy* pluginProcessPtr = pluginProcess.get(); - - m_pluginProcesses.append(pluginProcess.release()); + m_pluginProcesses.append(pluginProcess.release()); + return pluginProcessPtr; + } + } - return pluginProcessPtr; + return nullptr; } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h index f84521a49..307c39810 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h @@ -30,8 +30,10 @@ #include "PluginModuleInfo.h" #include "PluginProcess.h" +#include "PluginProcessAttributes.h" #include "WebProcessProxyMessages.h" #include <wtf/Forward.h> +#include <wtf/HashSet.h> #include <wtf/Noncopyable.h> #include <wtf/Vector.h> @@ -51,23 +53,27 @@ class PluginProcessManager { public: static PluginProcessManager& shared(); - void getPluginProcessConnection(const PluginInfoStore&, const String& pluginPath, PluginProcess::Type, PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply>); + uint64_t pluginProcessToken(const PluginModuleInfo&, PluginProcessType, PluginProcessSandboxPolicy); + + void getPluginProcessConnection(uint64_t pluginProcessToken, 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); #if PLATFORM(MAC) - void setApplicationIsOccluded(bool); + void setProcessSuppressionEnabled(bool); #endif private: PluginProcessManager(); - PluginProcessProxy* getOrCreatePluginProcess(const PluginModuleInfo&, PluginProcess::Type); - PluginProcessProxy* pluginProcessWithPath(const String& pluginPath, PluginProcess::Type); + PluginProcessProxy* getOrCreatePluginProcess(uint64_t pluginProcessToken); + + Vector<std::pair<PluginProcessAttributes, uint64_t>> m_pluginProcessTokens; + HashSet<uint64_t> m_knownTokens; - Vector<RefPtr<PluginProcessProxy> > m_pluginProcesses; + Vector<RefPtr<PluginProcessProxy>> m_pluginProcesses; }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp index 5a49f9598..107ad1633 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp @@ -28,13 +28,13 @@ #if ENABLE(PLUGIN_PROCESS) +#include "PluginProcessConnectionManagerMessages.h" #include "PluginProcessCreationParameters.h" #include "PluginProcessManager.h" #include "PluginProcessMessages.h" #include "WebContext.h" #include "WebCoreArgumentCoders.h" #include "WebPluginSiteDataManager.h" -#include "WebProcessMessages.h" #include "WebProcessProxy.h" #include <WebCore/NotImplemented.h> #include <WebCore/RunLoop.h> @@ -47,44 +47,48 @@ using namespace WebCore; namespace WebKit { -static const double minimumLifetime = 30 * 60; -static const double shutdownTimeout = 10 * 60; +static const double minimumLifetime = 2 * 60; +static const double snapshottingMinimumLifetime = 30; -PassRefPtr<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginModuleInfo& pluginInfo, PluginProcess::Type processType) +static const double shutdownTimeout = 1 * 60; +static const double snapshottingShutdownTimeout = 15; + +PassRefPtr<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginProcessAttributes& pluginProcessAttributes, uint64_t pluginProcessToken) { - return adoptRef(new PluginProcessProxy(PluginProcessManager, pluginInfo, processType)); + return adoptRef(new PluginProcessProxy(PluginProcessManager, pluginProcessAttributes, pluginProcessToken)); } -PluginProcessProxy::PluginProcessProxy(PluginProcessManager* PluginProcessManager, const PluginModuleInfo& pluginInfo, PluginProcess::Type processType) +PluginProcessProxy::PluginProcessProxy(PluginProcessManager* PluginProcessManager, const PluginProcessAttributes& pluginProcessAttributes, uint64_t pluginProcessToken) : m_pluginProcessManager(PluginProcessManager) - , m_pluginInfo(pluginInfo) + , m_pluginProcessAttributes(pluginProcessAttributes) + , m_pluginProcessToken(pluginProcessToken) , m_numPendingConnectionRequests(0) #if PLATFORM(MAC) , m_modalWindowIsShowing(false) , m_fullscreenWindowIsShowing(false) , m_preFullscreenAppPresentationOptions(0) #endif - , m_processType(processType) { - ProcessLauncher::LaunchOptions launchOptions; - launchOptions.processType = ProcessLauncher::PluginProcess; - - platformInitializeLaunchOptions(launchOptions, pluginInfo); - - m_processLauncher = ProcessLauncher::create(this, launchOptions); + connect(); } PluginProcessProxy::~PluginProcessProxy() { } +void PluginProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions) +{ + launchOptions.processType = ProcessLauncher::PluginProcess; + platformGetLaunchOptions(launchOptions, m_pluginProcessAttributes); +} + // 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()) { + if (isLaunching()) { m_numPendingConnectionRequests++; return; } @@ -99,7 +103,7 @@ void PluginProcessProxy::getSitesWithData(WebPluginSiteDataManager* webPluginSit ASSERT(!m_pendingGetSitesReplies.contains(callbackID)); m_pendingGetSitesReplies.set(callbackID, webPluginSiteDataManager); - if (m_processLauncher->isLaunching()) { + if (isLaunching()) { m_pendingGetSitesRequests.append(callbackID); return; } @@ -113,7 +117,7 @@ void PluginProcessProxy::clearSiteData(WebPluginSiteDataManager* webPluginSiteDa ASSERT(!m_pendingClearSiteDataReplies.contains(callbackID)); m_pendingClearSiteDataReplies.set(callbackID, webPluginSiteDataManager); - if (m_processLauncher->isLaunching()) { + if (isLaunching()) { ClearSiteDataRequest request; request.sites = sites; request.flags = flags; @@ -127,11 +131,6 @@ void PluginProcessProxy::clearSiteData(WebPluginSiteDataManager* webPluginSiteDa 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. @@ -157,11 +156,6 @@ void PluginProcessProxy::pluginProcessCrashedOrFailedToLaunch() m_pluginProcessManager->removePluginProcessProxy(this); } -void PluginProcessProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& decoder) -{ - didReceivePluginProcessProxyMessage(connection, messageID, decoder); -} - void PluginProcessProxy::didClose(CoreIPC::Connection*) { #if PLATFORM(MAC) @@ -174,7 +168,7 @@ void PluginProcessProxy::didClose(CoreIPC::Connection*) const Vector<WebContext*>& contexts = WebContext::allContexts(); for (size_t i = 0; i < contexts.size(); ++i) - contexts[i]->sendToAllProcesses(Messages::WebProcess::PluginProcessCrashed(m_pluginInfo.path, m_processType)); + contexts[i]->sendToAllProcesses(Messages::PluginProcessConnectionManager::PluginProcessCrashed(m_pluginProcessToken)); // This will cause us to be deleted. pluginProcessCrashedOrFailedToLaunch(); @@ -197,19 +191,20 @@ void PluginProcessProxy::didFinishLaunching(ProcessLauncher*, CoreIPC::Connectio #if PLATFORM(MAC) m_connection->setShouldCloseConnectionOnMachExceptions(); #elif PLATFORM(QT) - m_connection->setShouldCloseConnectionOnProcessTermination(m_processLauncher->processIdentifier()); + m_connection->setShouldCloseConnectionOnProcessTermination(processIdentifier()); #endif m_connection->open(); PluginProcessCreationParameters parameters; - - parameters.pluginPath = m_pluginInfo.path; - parameters.processType = m_processType; - - parameters.minimumLifetime = minimumLifetime; - parameters.terminationTimeout = shutdownTimeout; - + parameters.processType = m_pluginProcessAttributes.processType; + if (parameters.processType == PluginProcessTypeSnapshot) { + parameters.minimumLifetime = snapshottingMinimumLifetime; + parameters.terminationTimeout = snapshottingShutdownTimeout; + } else { + parameters.minimumLifetime = minimumLifetime; + parameters.terminationTimeout = shutdownTimeout; + } platformInitializePluginProcess(parameters); // Initialize the plug-in host process. @@ -232,8 +227,8 @@ void PluginProcessProxy::didFinishLaunching(ProcessLauncher*, CoreIPC::Connectio m_numPendingConnectionRequests = 0; #if PLATFORM(MAC) - if (WebContext::applicationIsOccluded()) - m_connection->send(Messages::PluginProcess::SetApplicationIsOccluded(true), 0); + if (WebContext::canEnableProcessSuppressionForGlobalChildProcesses()) + setProcessSuppressionEnabled(true); #endif } diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h index 194d7a373..1cb2268a9 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h @@ -28,9 +28,11 @@ #if ENABLE(PLUGIN_PROCESS) +#include "ChildProcessProxy.h" #include "Connection.h" #include "PluginModuleInfo.h" #include "PluginProcess.h" +#include "PluginProcessAttributes.h" #include "ProcessLauncher.h" #include "WebProcessProxyMessages.h" #include <wtf/Deque.h> @@ -61,14 +63,15 @@ struct RawPluginMetaData { }; #endif -class PluginProcessProxy : public RefCounted<PluginProcessProxy>, CoreIPC::Connection::Client, ProcessLauncher::Client { +class PluginProcessProxy : public ChildProcessProxy { public: - static PassRefPtr<PluginProcessProxy> create(PluginProcessManager*, const PluginModuleInfo&, PluginProcess::Type); + static PassRefPtr<PluginProcessProxy> create(PluginProcessManager*, const PluginProcessAttributes&, uint64_t pluginProcessToken); ~PluginProcessProxy(); - const PluginModuleInfo& pluginInfo() const { return m_pluginInfo; } + const PluginProcessAttributes& pluginProcessAttributes() const { return m_pluginProcessAttributes; } + uint64_t pluginProcessToken() const { return m_pluginProcessToken; } - // Asks the plug-in process to create a new connection to a web process. The connection identifier will be + // 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>); @@ -78,15 +81,10 @@ public: // 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(); - bool isValid() const { return m_connection; } - PluginProcess::Type processType() const { return m_processType; } - #if PLATFORM(MAC) - void setApplicationIsOccluded(bool); + void setProcessSuppressionEnabled(bool); // Returns whether the plug-in needs the heap to be marked executable. static bool pluginNeedsExecutableHeap(const PluginModuleInfo&); @@ -100,12 +98,17 @@ public: #endif private: - PluginProcessProxy(PluginProcessManager*, const PluginModuleInfo&, PluginProcess::Type); + PluginProcessProxy(PluginProcessManager*, const PluginProcessAttributes&, uint64_t pluginProcessToken); + + virtual void getLaunchOptions(ProcessLauncher::LaunchOptions&) OVERRIDE; + void platformGetLaunchOptions(ProcessLauncher::LaunchOptions&, const PluginProcessAttributes&); void pluginProcessCrashedOrFailedToLaunch(); // CoreIPC::Connection::Client - virtual void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::MessageDecoder&) OVERRIDE; + virtual void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&) OVERRIDE; + virtual void didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&, OwnPtr<CoreIPC::MessageEncoder>&) OVERRIDE; + virtual void didClose(CoreIPC::Connection*) OVERRIDE; virtual void didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::StringReference messageReceiverName, CoreIPC::StringReference messageName) OVERRIDE; @@ -113,7 +116,6 @@ private: virtual void didFinishLaunching(ProcessLauncher*, CoreIPC::Connection::Identifier); // Message handlers - void didReceivePluginProcessProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::MessageDecoder&); void didCreateWebProcessConnection(const CoreIPC::Attachment&, bool supportsAsynchronousPluginInitialization); void didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID); void didClearSiteData(uint64_t callbackID); @@ -132,27 +134,27 @@ private: void endModal(); void applicationDidBecomeActive(); + void openPluginPreferencePane(); + void launchProcess(const String& launchPath, const Vector<String>& arguments, bool& result); + void launchApplicationAtURL(const String& urlString, const Vector<String>& arguments, bool& result); + void openURL(const String& url, bool& result, int32_t& status, String& launchedURLString); #endif - static void platformInitializeLaunchOptions(ProcessLauncher::LaunchOptions&, const PluginModuleInfo& pluginInfo); void platformInitializePluginProcess(PluginProcessCreationParameters& parameters); // The plug-in host process manager. PluginProcessManager* m_pluginProcessManager; - - // Information about the plug-in. - PluginModuleInfo m_pluginInfo; + + PluginProcessAttributes m_pluginProcessAttributes; + uint64_t m_pluginProcessToken; // 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; + Deque<RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply>> m_pendingConnectionReplies; Vector<uint64_t> m_pendingGetSitesRequests; - HashMap<uint64_t, RefPtr<WebPluginSiteDataManager> > m_pendingGetSitesReplies; + HashMap<uint64_t, RefPtr<WebPluginSiteDataManager>> m_pendingGetSitesReplies; struct ClearSiteDataRequest { Vector<String> sites; @@ -161,7 +163,7 @@ private: uint64_t callbackID; }; Vector<ClearSiteDataRequest> m_pendingClearSiteDataRequests; - HashMap<uint64_t, RefPtr<WebPluginSiteDataManager> > m_pendingClearSiteDataReplies; + 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. @@ -174,8 +176,6 @@ private: bool m_fullscreenWindowIsShowing; unsigned m_preFullscreenAppPresentationOptions; #endif - - PluginProcess::Type m_processType; }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in index 183cb0c68..aa3b106c5 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in @@ -31,6 +31,18 @@ messages -> PluginProcessProxy { #if PLATFORM(MAC) SetModalWindowIsShowing(bool modalWindowIsShowing) SetFullscreenWindowIsShowing(bool fullscreenWindowIsShowing) + + # Open the plug-ins preference pane (as specified in the plug-in's Info.plist file). + OpenPluginPreferencePane() + + # Returns true if the UI process launched the process. + LaunchProcess(WTF::String launchPath, Vector<WTF::String> arguments) -> (bool result) + + # Returns true if the UI process launched the application. + LaunchApplicationAtURL(WTF::String url, Vector<WTF::String> arguments) -> (bool result) + + # Returns true if the UI process did open the URL. + OpenURL(WTF::String urlString) -> (bool result, int32_t status, WTF::String launchedURLString) #endif } diff --git a/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp b/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp index ff96ab96c..005591cc8 100644 --- a/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp +++ b/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp @@ -139,9 +139,7 @@ void WebPluginSiteDataManager::invalidate() invalidateCallbackMap(m_arrayCallbacks); #if ENABLE(PLUGIN_PROCESS) - deleteAllValues(m_pendingGetSitesWithData); m_pendingGetSitesWithData.clear(); - deleteAllValues(m_pendingClearSiteData); m_pendingClearSiteData.clear(); #endif } @@ -162,7 +160,7 @@ void WebPluginSiteDataManager::getSitesWithData(PassRefPtr<ArrayCallback> prpCal ASSERT(!m_pendingGetSitesWithData.contains(callbackID)); GetSitesWithDataState* state = new GetSitesWithDataState(this, callbackID); - m_pendingGetSitesWithData.set(callbackID, state); + m_pendingGetSitesWithData.set(callbackID, adoptPtr(state)); state->getSitesWithDataForNextPlugin(); #else Vector<PluginModuleInfo> plugins = m_webContext->pluginInfoStore().plugins(); @@ -183,7 +181,7 @@ void WebPluginSiteDataManager::didGetSitesWithData(const Vector<String>& sites, return; } - Vector<RefPtr<APIObject> > sitesWK(sites.size()); + Vector<RefPtr<APIObject>> sitesWK(sites.size()); for (size_t i = 0; i < sites.size(); ++i) sitesWK[i] = WebString::create(sites[i]); @@ -222,7 +220,7 @@ void WebPluginSiteDataManager::clearSiteData(ImmutableArray* sites, uint64_t fla ASSERT(!m_pendingClearSiteData.contains(callbackID)); ClearSiteDataState* state = new ClearSiteDataState(this, sitesVector, flags, maxAgeInSeconds, callbackID); - m_pendingClearSiteData.set(callbackID, state); + m_pendingClearSiteData.set(callbackID, adoptPtr(state)); state->clearSiteDataForNextPlugin(); #else Vector<PluginModuleInfo> plugins = m_webContext->pluginInfoStore().plugins(); @@ -267,7 +265,7 @@ void WebPluginSiteDataManager::didGetSitesWithDataForSinglePlugin(const Vector<S void WebPluginSiteDataManager::didGetSitesWithDataForAllPlugins(const Vector<String>& sites, uint64_t callbackID) { - OwnPtr<GetSitesWithDataState> state = adoptPtr(m_pendingGetSitesWithData.take(callbackID)); + OwnPtr<GetSitesWithDataState> state = m_pendingGetSitesWithData.take(callbackID); ASSERT(state); didGetSitesWithData(sites, callbackID); @@ -283,7 +281,7 @@ void WebPluginSiteDataManager::didClearSiteDataForSinglePlugin(uint64_t callback void WebPluginSiteDataManager::didClearSiteDataForAllPlugins(uint64_t callbackID) { - OwnPtr<ClearSiteDataState> state = adoptPtr(m_pendingClearSiteData.take(callbackID)); + OwnPtr<ClearSiteDataState> state = m_pendingClearSiteData.take(callbackID); ASSERT(state); didClearSiteData(callbackID); diff --git a/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.h b/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.h index 9b025cc38..1edeceef8 100644 --- a/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.h +++ b/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.h @@ -41,10 +41,8 @@ class WebProcessProxy; typedef GenericCallback<WKArrayRef> ArrayCallback; -class WebPluginSiteDataManager : public APIObject { +class WebPluginSiteDataManager : public TypedAPIObject<APIObject::TypePluginSiteDataManager> { public: - static const Type APIType = TypePluginSiteDataManager; - static PassRefPtr<WebPluginSiteDataManager> create(WebContext*); virtual ~WebPluginSiteDataManager(); @@ -67,21 +65,19 @@ public: 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; + 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; + HashMap<uint64_t, OwnPtr<GetSitesWithDataState>> m_pendingGetSitesWithData; class ClearSiteDataState; - HashMap<uint64_t, ClearSiteDataState*> m_pendingClearSiteData; + HashMap<uint64_t, OwnPtr<ClearSiteDataState>> m_pendingClearSiteData; #endif }; diff --git a/Source/WebKit2/UIProcess/Plugins/mac/PluginInfoStoreMac.mm b/Source/WebKit2/UIProcess/Plugins/mac/PluginInfoStoreMac.mm index 6ebde6476..61367c51b 100644 --- a/Source/WebKit2/UIProcess/Plugins/mac/PluginInfoStoreMac.mm +++ b/Source/WebKit2/UIProcess/Plugins/mac/PluginInfoStoreMac.mm @@ -61,7 +61,7 @@ Vector<String> PluginInfoStore::pluginPathsInDirectory(const String& directory) { Vector<String> pluginPaths; - RetainPtr<CFStringRef> directoryCFString(AdoptCF, safeCreateCFString(directory)); + RetainPtr<CFStringRef> directoryCFString = adoptCF(safeCreateCFString(directory)); NSArray *filenames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:(NSString *)directoryCFString.get() error:nil]; for (NSString *filename in filenames) @@ -109,7 +109,7 @@ static bool checkForPreferredPlugin(Vector<PluginModuleInfo>& alreadyLoadedPlugi static bool shouldBlockPlugin(const PluginModuleInfo& plugin) { - return PluginInfoStore::policyForPlugin(plugin) == PluginModuleBlocked; + return PluginInfoStore::defaultLoadPolicyForPlugin(plugin) == PluginModuleBlocked; } bool PluginInfoStore::shouldUsePlugin(Vector<PluginModuleInfo>& alreadyLoadedPlugins, const PluginModuleInfo& plugin) @@ -132,49 +132,39 @@ bool PluginInfoStore::shouldUsePlugin(Vector<PluginModuleInfo>& alreadyLoadedPlu if (!checkForPreferredPlugin(alreadyLoadedPlugins, plugin, "com.apple.java.JavaAppletPlugin", oracleJavaAppletPluginBundleIdentifier)) return false; -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 - if (plugin.bundleIdentifier == "com.apple.java.JavaAppletPlugin" && shouldBlockPlugin(plugin) && !WKIsJavaPlugInActive()) { - // If the Apple Java plug-in is blocked and there's no Java runtime installed, just pretend that the plug-in doesn't exist. - return false; - } -#endif - return true; } -PluginModuleLoadPolicy PluginInfoStore::policyForPlugin(const PluginModuleInfo& plugin) +PluginModuleLoadPolicy PluginInfoStore::defaultLoadPolicyForPlugin(const PluginModuleInfo& plugin) { if (WKShouldBlockPlugin(plugin.bundleIdentifier, plugin.versionString)) return PluginModuleBlocked; - if (plugin.bundleIdentifier == oracleJavaAppletPluginBundleIdentifier && !WKIsJavaPlugInActive()) - return PluginModuleInactive; - return PluginModuleLoadNormally; } -bool PluginInfoStore::reactivateInactivePlugin(const PluginModuleInfo& plugin) -{ -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 - if (plugin.bundleIdentifier == oracleJavaAppletPluginBundleIdentifier) { - WKActivateJavaPlugIn(); - return true; - } -#endif - - return false; -} - 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)); + RetainPtr<CFStringRef> extensionCFString = adoptCF(safeCreateCFString(extension)); return WKGetMIMETypeForExtension((NSString *)extensionCFString.get()); } +PluginModuleInfo PluginInfoStore::findPluginWithBundleIdentifier(const String& bundleIdentifier) +{ + loadPluginsIfNecessary(); + + for (size_t i = 0; i < m_plugins.size(); ++i) { + if (m_plugins[i].bundleIdentifier == bundleIdentifier) + return m_plugins[i]; + } + + return PluginModuleInfo(); +} + } // namespace WebKit #endif // ENABLE(NETSCAPE_PLUGIN_API) diff --git a/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessManagerMac.mm b/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessManagerMac.mm index 6a974dad7..771cf7801 100644 --- a/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessManagerMac.mm +++ b/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessManagerMac.mm @@ -32,11 +32,11 @@ namespace WebKit { -void PluginProcessManager::setApplicationIsOccluded(bool applicationIsOccluded) +void PluginProcessManager::setProcessSuppressionEnabled(bool processSuppressionEnabled) { size_t processCount = m_pluginProcesses.size(); for (size_t i = 0; i < processCount; ++i) - m_pluginProcesses[i]->setApplicationIsOccluded(applicationIsOccluded); + m_pluginProcesses[i]->setProcessSuppressionEnabled(processSuppressionEnabled); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm b/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm index e92ef9e76..4ce88b3d2 100644 --- a/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm +++ b/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm @@ -28,17 +28,20 @@ #if ENABLE(PLUGIN_PROCESS) +#import "DynamicLinkerEnvironmentExtractor.h" #import "EnvironmentVariables.h" #import "PluginProcessCreationParameters.h" #import "PluginProcessMessages.h" #import "WebKitSystemInterface.h" #import <WebCore/FileSystem.h> +#import <WebCore/KURL.h> +#import <WebCore/RuntimeApplicationChecks.h> +#import <crt_externs.h> +#import <mach-o/dyld.h> #import <spawn.h> #import <wtf/text/CString.h> -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 #import <QuartzCore/CARemoteLayerServer.h> -#endif @interface WKPlaceholderModalWindow : NSWindow @end @@ -54,8 +57,6 @@ @end -NSString * const WebKit2PlugInSandboxProfileDirectoryPathKey = @"WebKit2PlugInSandboxProfileDirectoryPath"; - using namespace WebCore; namespace WebKit { @@ -91,6 +92,9 @@ bool PluginProcessProxy::createPropertyListFile(const PluginModuleInfo& plugin) posix_spawnattr_setbinpref_np(&attr, 1, cpuTypes, &outCount); EnvironmentVariables environmentVariables; + + DynamicLinkerEnvironmentExtractor environmentExtractor([[NSBundle mainBundle] executablePath], _NSGetMachExecuteHeader()->cputype); + environmentExtractor.getExtractedEnvironmentVariables(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 @@ -119,42 +123,54 @@ bool PluginProcessProxy::createPropertyListFile(const PluginModuleInfo& plugin) return true; } -void PluginProcessProxy::platformInitializeLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions, const PluginModuleInfo& pluginInfo) +#if HAVE(XPC) +static bool shouldUseXPC() +{ + if (id value = [[NSUserDefaults standardUserDefaults] objectForKey:@"WebKit2UseXPCServiceForWebProcess"]) + return [value boolValue]; + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + // FIXME: Temporary workaround for <rdar://problem/13236883> + if (applicationIsSafari()) + return false; + + return true; +#else + return false; +#endif +} +#endif + +void PluginProcessProxy::platformGetLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions, const PluginProcessAttributes& pluginProcessAttributes) { - launchOptions.architecture = pluginInfo.pluginArchitecture; - launchOptions.executableHeap = PluginProcessProxy::pluginNeedsExecutableHeap(pluginInfo); + launchOptions.architecture = pluginProcessAttributes.moduleInfo.pluginArchitecture; + launchOptions.executableHeap = PluginProcessProxy::pluginNeedsExecutableHeap(pluginProcessAttributes.moduleInfo); + launchOptions.extraInitializationData.add("plugin-path", pluginProcessAttributes.moduleInfo.path); + + // FIXME: Don't allow this if the UI process is sandboxed. + if (pluginProcessAttributes.sandboxPolicy == PluginProcessSandboxPolicyUnsandboxed) + launchOptions.extraInitializationData.add("disable-sandbox", "1"); + #if HAVE(XPC) - launchOptions.useXPC = false; + launchOptions.useXPC = shouldUseXPC(); #endif } void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationParameters& parameters) { - // For know only Flash is known to behave with asynchronous plug-in initialization. - parameters.supportsAsynchronousPluginInitialization = m_pluginInfo.bundleIdentifier == "com.macromedia.Flash Player.plugin"; + // For now only Flash is known to behave with asynchronous plug-in initialization. + parameters.supportsAsynchronousPluginInitialization = m_pluginProcessAttributes.moduleInfo.bundleIdentifier == "com.macromedia.Flash Player.plugin"; #if USE(ACCELERATED_COMPOSITING) && HAVE(HOSTED_CORE_ANIMATION) - parameters.parentProcessName = [[NSProcessInfo processInfo] processName]; -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 mach_port_t renderServerPort = [[CARemoteLayerServer sharedServer] serverPort]; -#else - mach_port_t renderServerPort = WKInitializeRenderServer(); -#endif - if (renderServerPort != MACH_PORT_NULL) parameters.acceleratedCompositingPort = CoreIPC::MachPort(renderServerPort, MACH_MSG_TYPE_COPY_SEND); #endif - - // FIXME: We should rip this out once we have a good place to install plug-in - // sandbox profiles. - NSString* sandboxProfileDirectoryPath = [[NSUserDefaults standardUserDefaults] stringForKey:WebKit2PlugInSandboxProfileDirectoryPathKey]; - if (sandboxProfileDirectoryPath) - parameters.sandboxProfileDirectoryPath = String(sandboxProfileDirectoryPath); } bool PluginProcessProxy::getPluginProcessSerialNumber(ProcessSerialNumber& pluginProcessSerialNumber) { - pid_t pluginProcessPID = m_processLauncher->processIdentifier(); + pid_t pluginProcessPID = processIdentifier(); #if COMPILER(CLANG) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" @@ -282,7 +298,7 @@ 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 = 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 @@ -316,12 +332,144 @@ void PluginProcessProxy::applicationDidBecomeActive() makePluginProcessTheFrontProcess(); } -void PluginProcessProxy::setApplicationIsOccluded(bool applicationIsOccluded) +void PluginProcessProxy::setProcessSuppressionEnabled(bool processSuppressionEnabled) { if (!isValid()) return; - m_connection->send(Messages::PluginProcess::SetApplicationIsOccluded(applicationIsOccluded), 0); + m_connection->send(Messages::PluginProcess::SetProcessSuppressionEnabled(processSuppressionEnabled), 0); +} + +void PluginProcessProxy::openPluginPreferencePane() +{ + if (!m_pluginProcessAttributes.moduleInfo.preferencePanePath) + return; + + NSURL *preferenceURL = [NSURL fileURLWithPath:m_pluginProcessAttributes.moduleInfo.preferencePanePath]; + if (!preferenceURL) { + LOG_ERROR("Creating URL for preference pane path \"%@\" failed.", (NSString *)m_pluginProcessAttributes.moduleInfo.preferencePanePath); + return; + } + + NSArray *preferenceURLs = [NSArray arrayWithObject:preferenceURL]; + + LSLaunchURLSpec prefSpec; + prefSpec.appURL = 0; + prefSpec.itemURLs = reinterpret_cast<CFArrayRef>(preferenceURLs); + prefSpec.passThruParams = 0; + prefSpec.launchFlags = kLSLaunchAsync | kLSLaunchDontAddToRecents; + prefSpec.asyncRefCon = 0; + + OSStatus error = LSOpenFromURLSpec(&prefSpec, 0); + if (error != noErr) + LOG_ERROR("LSOpenFromURLSpec to open \"%@\" failed with error %d.", (NSString *)m_pluginProcessAttributes.moduleInfo.preferencePanePath, error); +} + +static bool isFlashUpdater(const String& launchPath, const Vector<String>& arguments) +{ + if (launchPath != "/Applications/Utilities/Adobe Flash Player Install Manager.app/Contents/MacOS/Adobe Flash Player Install Manager") + return false; + + if (arguments.size() != 1) + return false; + + if (arguments[0] != "-update") + return false; + + return true; +} + +static bool shouldLaunchProcess(const PluginProcessAttributes& pluginProcessAttributes, const String& launchPath, const Vector<String>& arguments) +{ + if (pluginProcessAttributes.moduleInfo.bundleIdentifier == "com.macromedia.Flash Player.plugin") + return isFlashUpdater(launchPath, arguments); + + return false; +} + +void PluginProcessProxy::launchProcess(const String& launchPath, const Vector<String>& arguments, bool& result) +{ + if (!shouldLaunchProcess(m_pluginProcessAttributes, launchPath, arguments)) { + result = false; + return; + } + + result = true; + + RetainPtr<NSMutableArray> argumentsArray = adoptNS([[NSMutableArray alloc] initWithCapacity:arguments.size()]); + for (size_t i = 0; i < arguments.size(); ++i) + [argumentsArray addObject:(NSString *)arguments[i]]; + + [NSTask launchedTaskWithLaunchPath:launchPath arguments:argumentsArray.get()]; +} + +static bool isJavaUpdaterURL(const PluginProcessAttributes& pluginProcessAttributes, const String& urlString) +{ + NSURL *url = [NSURL URLWithString:urlString]; + if (![url isFileURL]) + return false; + + NSString *javaUpdaterPath = [NSString pathWithComponents:[NSArray arrayWithObjects:(NSString *)pluginProcessAttributes.moduleInfo.path, @"Contents/Resources/Java Updater.app", nil]]; + return [url.path isEqualToString:javaUpdaterPath]; +} + +static bool shouldLaunchApplicationAtURL(const PluginProcessAttributes& pluginProcessAttributes, const String& urlString) +{ + if (pluginProcessAttributes.moduleInfo.bundleIdentifier == "com.oracle.java.JavaAppletPlugin") + return isJavaUpdaterURL(pluginProcessAttributes, urlString); + + return false; +} + +void PluginProcessProxy::launchApplicationAtURL(const String& urlString, const Vector<String>& arguments, bool& result) +{ + if (!shouldLaunchApplicationAtURL(m_pluginProcessAttributes, urlString)) { + result = false; + return; + } + + result = true; + + RetainPtr<NSMutableArray> argumentsArray = adoptNS([[NSMutableArray alloc] initWithCapacity:arguments.size()]); + for (size_t i = 0; i < arguments.size(); ++i) + [argumentsArray addObject:(NSString *)arguments[i]]; + + NSDictionary *configuration = [NSDictionary dictionaryWithObject:argumentsArray.get() forKey:NSWorkspaceLaunchConfigurationArguments]; + [[NSWorkspace sharedWorkspace] launchApplicationAtURL:[NSURL URLWithString:urlString] options:NSWorkspaceLaunchAsync configuration:configuration error:nullptr]; +} + +static bool isSilverlightPreferencesURL(const PluginProcessAttributes& pluginProcessAttributes, const String& urlString) +{ + NSURL *silverlightPreferencesURL = [NSURL fileURLWithPathComponents:[NSArray arrayWithObjects:(NSString *)pluginProcessAttributes.moduleInfo.path, @"Contents/Resources/Silverlight Preferences.app", nil]]; + + return [[NSURL URLWithString:urlString] isEqual:silverlightPreferencesURL]; +} + +static bool shouldOpenURL(const PluginProcessAttributes& pluginProcessAttributes, const String& urlString) +{ + if (pluginProcessAttributes.moduleInfo.bundleIdentifier == "com.microsoft.SilverlightPlugin") + return isSilverlightPreferencesURL(pluginProcessAttributes, urlString); + + return false; +} + +void PluginProcessProxy::openURL(const String& urlString, bool& result, int32_t& status, String& launchedURLString) +{ + if (!shouldOpenURL(m_pluginProcessAttributes, urlString)) { + result = false; + return; + } + + result = true; + CFURLRef launchedURL; + status = LSOpenCFURLRef(KURL(ParsedURLString, urlString).createCFURL().get(), &launchedURL); + + if (launchedURL) { + launchedURLString = KURL(launchedURL).string(); + CFRelease(launchedURL); + } + + result = false; } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp b/Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp index cb4884d4c..47b118a4b 100644 --- a/Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp +++ b/Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp @@ -29,7 +29,6 @@ #if ENABLE(PLUGIN_PROCESS) #include "ProcessExecutablePath.h" -#include "QtDefaultDataLocation.h" #include <QByteArray> #include <QCoreApplication> #include <QDateTime> @@ -41,6 +40,7 @@ #include <QJsonObject> #include <QMap> #include <QProcess> +#include <QStandardPaths> #include <QStringBuilder> #include <QVariant> #include <WebCore/FileSystem.h> @@ -51,8 +51,9 @@ namespace WebKit { class PluginProcessCreationParameters; -void PluginProcessProxy::platformInitializeLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions, const PluginModuleInfo& pluginInfo) +void PluginProcessProxy::platformGetLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions, const PluginProcessAttributes& pluginProcessAttributes) { + launchOptions.extraInitializationData.add("plugin-path", pluginProcessAttributes.moduleInfo.path); } void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationParameters&) @@ -61,10 +62,24 @@ void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationPa static PassOwnPtr<QFile> cacheFile() { - static QString cacheFilePath = defaultDataLocation() % QStringLiteral("plugin_meta_data.json"); + QString cachePath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); + if (cachePath.isEmpty()) + return PassOwnPtr<QFile>(); + + // This should match the path set through WKContextSetDiskCacheDirectory. + cachePath.append(QDir::separator()).append(QStringLiteral(".QtWebKit")).append(QDir::separator()); + QString cacheFilePath = cachePath % QStringLiteral("plugin_meta_data.json"); + + QDir::root().mkpath(cachePath); return adoptPtr(new QFile(cacheFilePath)); } +static void removeCacheFile() +{ + if (OwnPtr<QFile> file = cacheFile()) + file->remove(); +} + struct ReadResult { enum Tag { Empty, @@ -76,7 +91,7 @@ struct ReadResult { static ReadResult::Tag readMetaDataFromCacheFile(QJsonDocument& result) { OwnPtr<QFile> file = cacheFile(); - if (!file->open(QFile::ReadOnly)) + if (!file || !file->open(QFile::ReadOnly)) return ReadResult::Empty; QByteArray data = file->readAll(); if (data.isEmpty()) @@ -96,14 +111,9 @@ static ReadResult::Tag readMetaDataFromCacheFile(QJsonDocument& result) static void writeToCacheFile(const QJsonArray& array) { OwnPtr<QFile> file = cacheFile(); - if (!file->open(QFile::WriteOnly | QFile::Truncate)) { - // It should never but let's be pessimistic, it is the file system after all. - qWarning("Cannot write into plugin meta data cache file: %s\n", qPrintable(file->fileName())); - return; - } - - // Don't care about write error here. We will detect it later. - file->write(QJsonDocument(array).toJson()); + if (file && file->open(QFile::WriteOnly | QFile::Truncate)) + // Don't care about write error here. We will detect it later. + file->write(QJsonDocument(array).toJson()); } static void appendToCacheFile(const QJsonObject& object) @@ -139,7 +149,7 @@ static MetaDataResult::Tag tryReadPluginMetaDataFromCacheFile(const QString& can for (QJsonArray::const_iterator i = array.constBegin(); i != array.constEnd(); ++i) { QJsonValue item = *i; if (!item.isObject()) { - cacheFile()->remove(); + removeCacheFile(); return MetaDataResult::NotAvailable; } @@ -147,7 +157,7 @@ static MetaDataResult::Tag tryReadPluginMetaDataFromCacheFile(const QString& can if (object.value(QStringLiteral("path")).toString() == canonicalPluginPath) { QString timestampString = object.value(QStringLiteral("timestamp")).toString(); if (timestampString.isEmpty()) { - cacheFile()->remove(); + removeCacheFile(); return MetaDataResult::NotAvailable; } QDateTime timestamp = QDateTime::fromString(timestampString); @@ -168,7 +178,7 @@ static MetaDataResult::Tag tryReadPluginMetaDataFromCacheFile(const QString& can if (result.mimeDescription.isEmpty()) { // Only the mime description is mandatory. // Don't trust in the cache file if it is empty. - cacheFile()->remove(); + removeCacheFile(); return MetaDataResult::NotAvailable; } diff --git a/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp b/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp index d4c9ec2c5..3726401f6 100644 --- a/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp +++ b/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp @@ -72,7 +72,7 @@ Vector<String> PluginInfoStore::pluginsDirectories() if (!mozillaPaths.isEmpty()) { Vector<String> paths; mozillaPaths.split(UChar(':'), /* allowEmptyEntries */ false, paths); - result.append(paths); + result.appendVector(paths); } return result; diff --git a/Source/WebKit2/UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp b/Source/WebKit2/UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp index 730dafeed..d52cae647 100644 --- a/Source/WebKit2/UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp +++ b/Source/WebKit2/UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp @@ -35,23 +35,24 @@ #include <WebCore/FileSystem.h> #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> -#if PLATFORM(GTK) || (PLATFORM(EFL) && ENABLE(GLIB_SUPPORT)) +#if PLATFORM(GTK) || PLATFORM(EFL) #include <glib.h> +#include <wtf/gobject/GOwnPtr.h> #endif using namespace WebCore; namespace WebKit { -void PluginProcessProxy::platformInitializeLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions, const PluginModuleInfo&) +void PluginProcessProxy::platformGetLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions, const PluginProcessAttributes& pluginProcessAttributes) { #if PLATFORM(EFL) && !defined(NDEBUG) const char* commandPrefix = getenv("PLUGIN_PROCESS_COMMAND_PREFIX"); if (commandPrefix && *commandPrefix) launchOptions.processCmdPrefix = String::fromUTF8(commandPrefix); -#else - UNUSED_PARAM(launchOptions); #endif + + launchOptions.extraInitializationData.add("plugin-path", pluginProcessAttributes.moduleInfo.path); } void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationParameters&) @@ -60,7 +61,7 @@ void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationPa bool PluginProcessProxy::scanPlugin(const String& pluginPath, RawPluginMetaData& result) { -#if PLATFORM(GTK) || (PLATFORM(EFL) && ENABLE(GLIB_SUPPORT)) +#if PLATFORM(GTK) || PLATFORM(EFL) CString binaryPath = fileSystemRepresentation(executablePathOfPluginProcess()); CString pluginPathCString = fileSystemRepresentation(pluginPath); char* argv[4]; @@ -70,7 +71,7 @@ bool PluginProcessProxy::scanPlugin(const String& pluginPath, RawPluginMetaData& argv[3] = 0; int status; - char* stdOut = 0; + GOwnPtr<char> stdOut; // If the disposition of SIGCLD signal is set to SIG_IGN (default) // then the signal will be ignored and g_spawn_sync() will not be @@ -84,16 +85,13 @@ bool PluginProcessProxy::scanPlugin(const String& pluginPath, RawPluginMetaData& sigaction(SIGCLD, &action, 0); } - if (!g_spawn_sync(0, argv, 0, G_SPAWN_STDERR_TO_DEV_NULL, 0, 0, &stdOut, 0, &status, 0)) + if (!g_spawn_sync(0, argv, 0, G_SPAWN_STDERR_TO_DEV_NULL, 0, 0, &stdOut.outPtr(), 0, &status, 0)) return false; - if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS || !stdOut) { - free(stdOut); + if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS || !stdOut) return false; - } - String stdOutString(reinterpret_cast<const UChar*>(stdOut)); - free(stdOut); + String stdOutString(reinterpret_cast<const UChar*>(stdOut.get())); Vector<String> lines; stdOutString.split(UChar('\n'), true, lines); @@ -105,9 +103,9 @@ bool PluginProcessProxy::scanPlugin(const String& pluginPath, RawPluginMetaData& result.description.swap(lines[1]); result.mimeDescription.swap(lines[2]); return !result.mimeDescription.isEmpty(); -#else // PLATFORM(GTK) || (PLATFORM(EFL) && ENABLE(GLIB_SUPPORT)) +#else // PLATFORM(GTK) || PLATFORM(EFL) return false; -#endif // PLATFORM(GTK) || (PLATFORM(EFL) && ENABLE(GLIB_SUPPORT)) +#endif // PLATFORM(GTK) || PLATFORM(EFL) } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp b/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp deleted file mode 100644 index 634225eaf..000000000 --- a/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/* - * 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) -{ -#if ENABLE(NETSCAPE_PLUGIN_API) - return NetscapePluginModule::getPluginInfo(pluginPath, plugin); -#else - UNUSED_PARAM(pluginPath); - UNUSED_PARAM(plugin); - return false; -#endif -} - -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 |
