diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebKit2/UIProcess/Plugins | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebKit2/UIProcess/Plugins')
15 files changed, 436 insertions, 674 deletions
diff --git a/Source/WebKit2/UIProcess/Plugins/PlugInAutoStartProvider.cpp b/Source/WebKit2/UIProcess/Plugins/PlugInAutoStartProvider.cpp index e5724032d..25075924e 100644 --- a/Source/WebKit2/UIProcess/Plugins/PlugInAutoStartProvider.cpp +++ b/Source/WebKit2/UIProcess/Plugins/PlugInAutoStartProvider.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2012-2014 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,10 +27,10 @@ #include "PlugInAutoStartProvider.h" #include "APIArray.h" -#include "ImmutableDictionary.h" -#include "WebContext.h" +#include "APIDictionary.h" #include "WebContextClient.h" #include "WebProcessMessages.h" +#include "WebProcessPool.h" #include <wtf/CurrentTime.h> using namespace WebCore; @@ -39,9 +39,11 @@ static const double plugInAutoStartExpirationTimeThreshold = 30 * 24 * 60 * 60; namespace WebKit { -PlugInAutoStartProvider::PlugInAutoStartProvider(WebContext* context) - : m_context(context) +PlugInAutoStartProvider::PlugInAutoStartProvider(WebProcessPool* processPool) + : m_processPool(processPool) { + m_hashToOriginMap.add(SessionID::defaultSessionID(), HashMap<unsigned, String>()); + m_autoStartTable.add(SessionID::defaultSessionID(), AutoStartTable()); } static double expirationTimeFromNow() @@ -49,64 +51,68 @@ static double expirationTimeFromNow() return currentTime() + plugInAutoStartExpirationTimeThreshold; } -void PlugInAutoStartProvider::addAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash) +void PlugInAutoStartProvider::addAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash, SessionID sessionID) { - if (m_hashToOriginMap.contains(plugInOriginHash)) + auto sessionIterator = m_hashToOriginMap.find(sessionID); + if (sessionIterator == m_hashToOriginMap.end()) { + if (m_hashToOriginMap.get(SessionID::defaultSessionID()).contains(plugInOriginHash)) + return; + sessionIterator = m_hashToOriginMap.set(sessionID, HashMap<unsigned, String>()).iterator; + } else if (sessionIterator->value.contains(plugInOriginHash) || m_hashToOriginMap.get(SessionID::defaultSessionID()).contains(plugInOriginHash)) return; - AutoStartTable::iterator it = m_autoStartTable.find(pageOrigin); - if (it == m_autoStartTable.end()) - it = m_autoStartTable.add(pageOrigin, PlugInAutoStartOriginHash()).iterator; + AutoStartTable::iterator it = m_autoStartTable.add(sessionID, AutoStartTable()).iterator->value.add(pageOrigin, PlugInAutoStartOriginMap()).iterator; double expirationTime = expirationTimeFromNow(); it->value.set(plugInOriginHash, expirationTime); - m_hashToOriginMap.set(plugInOriginHash, pageOrigin); + sessionIterator->value.set(plugInOriginHash, pageOrigin); - m_context->sendToAllProcesses(Messages::WebProcess::DidAddPlugInAutoStartOriginHash(plugInOriginHash, expirationTime)); - m_context->client().plugInAutoStartOriginHashesChanged(m_context); + m_processPool->sendToAllProcesses(Messages::WebProcess::DidAddPlugInAutoStartOriginHash(plugInOriginHash, expirationTime, sessionID)); + + if (!sessionID.isEphemeral()) + m_processPool->client().plugInAutoStartOriginHashesChanged(m_processPool); } -PlugInAutoStartOriginHash PlugInAutoStartProvider::autoStartOriginHashesCopy() const +SessionPlugInAutoStartOriginMap 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); + SessionPlugInAutoStartOriginMap sessionMap; + + for (const auto& sessionKeyOriginHash : m_autoStartTable) { + PlugInAutoStartOriginMap& map = sessionMap.add(sessionKeyOriginHash.key, PlugInAutoStartOriginMap()).iterator->value; + for (const auto& keyOriginHash : sessionKeyOriginHash.value) { + for (const auto& originHash : keyOriginHash.value) + map.set(originHash.key, originHash.value); + } } - return copyMap; + return sessionMap; } -PassRefPtr<ImmutableDictionary> PlugInAutoStartProvider::autoStartOriginsTableCopy() const +Ref<API::Dictionary> PlugInAutoStartProvider::autoStartOriginsTableCopy() const { - ImmutableDictionary::MapType map; - AutoStartTable::const_iterator end = m_autoStartTable.end(); + API::Dictionary::MapType map; + 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), API::Double::create(valueIt->value)); + for (const auto& stringOriginHash : m_autoStartTable.get(SessionID::defaultSessionID())) { + API::Dictionary::MapType hashMap; + for (const auto& originHash : stringOriginHash.value) { + if (now <= originHash.value) + hashMap.set(String::number(originHash.key), API::Double::create(originHash.value)); } - if (hashMap.size()) - map.set(it->key, ImmutableDictionary::create(std::move(hashMap))); + map.set(stringOriginHash.key, API::Dictionary::create(WTFMove(hashMap))); } - return ImmutableDictionary::create(std::move(map)); + return API::Dictionary::create(WTFMove(map)); } -void PlugInAutoStartProvider::setAutoStartOriginsTable(ImmutableDictionary& table) +void PlugInAutoStartProvider::setAutoStartOriginsTable(API::Dictionary& table) { setAutoStartOriginsTableWithItemsPassingTest(table, [](double) { return true; }); } -void PlugInAutoStartProvider::setAutoStartOriginsFilteringOutEntriesAddedAfterTime(ImmutableDictionary& table, double time) +void PlugInAutoStartProvider::setAutoStartOriginsFilteringOutEntriesAddedAfterTime(API::Dictionary& table, double time) { double adjustedTimestamp = time + plugInAutoStartExpirationTimeThreshold; setAutoStartOriginsTableWithItemsPassingTest(table, [adjustedTimestamp](double expirationTimestamp) { @@ -114,66 +120,72 @@ void PlugInAutoStartProvider::setAutoStartOriginsFilteringOutEntriesAddedAfterTi }); } -void PlugInAutoStartProvider::setAutoStartOriginsTableWithItemsPassingTest(ImmutableDictionary& table, std::function<bool(double expirationTimestamp)> isExpirationTimeAcceptable) +void PlugInAutoStartProvider::setAutoStartOriginsTableWithItemsPassingTest(API::Dictionary& table, std::function<bool(double expirationTimestamp)> isExpirationTimeAcceptable) { ASSERT(isExpirationTimeAcceptable); m_hashToOriginMap.clear(); m_autoStartTable.clear(); HashMap<unsigned, double> hashMap; + HashMap<unsigned, String>& hashToOriginMap = m_hashToOriginMap.add(SessionID::defaultSessionID(), HashMap<unsigned, String>()).iterator->value; + AutoStartTable& ast = m_autoStartTable.add(SessionID::defaultSessionID(), AutoStartTable()).iterator->value; - 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) { + for (auto& strDict : table.map()) { + PlugInAutoStartOriginMap hashes; + for (auto& hashTime : static_cast<API::Dictionary*>(strDict.value.get())->map()) { bool ok; - unsigned hash = hashIt->key.toUInt(&ok); + unsigned hash = hashTime.key.toUInt(&ok); if (!ok) continue; - if (hashIt->value->type() != API::Double::APIType) + if (hashTime.value->type() != API::Double::APIType) continue; - double expirationTime = static_cast<API::Double*>(hashIt->value.get())->value(); + double expirationTime = static_cast<API::Double*>(hashTime.value.get())->value(); if (!isExpirationTimeAcceptable(expirationTime)) continue; hashes.set(hash, expirationTime); hashMap.set(hash, expirationTime); - m_hashToOriginMap.set(hash, it->key); + hashToOriginMap.set(hash, strDict.key); } if (!hashes.isEmpty()) - m_autoStartTable.set(it->key, hashes); + ast.set(strDict.key, hashes); } - m_context->sendToAllProcesses(Messages::WebProcess::ResetPlugInAutoStartOriginHashes(hashMap)); + m_processPool->sendToAllProcesses(Messages::WebProcess::ResetPlugInAutoStartOriginDefaultHashes(hashMap)); } void PlugInAutoStartProvider::setAutoStartOriginsArray(API::Array& originList) { m_autoStartOrigins.clear(); - for (size_t i = 0, length = originList.size(); i < length; ++i) { - if (originList.at(i)->type() != API::String::APIType) - continue; - m_autoStartOrigins.append(static_cast<API::String*>(originList.at(i))->string()); - } + for (const auto& string : originList.elementsOfType<API::String>()) + m_autoStartOrigins.append(string->string()); } -void PlugInAutoStartProvider::didReceiveUserInteraction(unsigned plugInOriginHash) +void PlugInAutoStartProvider::didReceiveUserInteraction(unsigned plugInOriginHash, SessionID sessionID) { - HashMap<unsigned, String>::const_iterator it = m_hashToOriginMap.find(plugInOriginHash); - if (it == m_hashToOriginMap.end()) { - ASSERT_NOT_REACHED(); - return; + HashMap<WebCore::SessionID, HashMap<unsigned, String>>::const_iterator sessionIterator = m_hashToOriginMap.find(sessionID); + HashMap<unsigned, String>::const_iterator it; + bool contains = false; + if (sessionIterator != m_hashToOriginMap.end()) { + it = sessionIterator->value.find(plugInOriginHash); + contains = it != sessionIterator->value.end(); + } + if (!contains) { + sessionIterator = m_hashToOriginMap.find(SessionID::defaultSessionID()); + it = sessionIterator->value.find(plugInOriginHash); + if (it == sessionIterator->value.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); + m_autoStartTable.add(sessionID, AutoStartTable()).iterator->value.add(it->value, PlugInAutoStartOriginMap()).iterator->value.set(plugInOriginHash, newExpirationTime); + m_processPool->sendToAllProcesses(Messages::WebProcess::DidAddPlugInAutoStartOriginHash(plugInOriginHash, newExpirationTime, sessionID)); + m_processPool->client().plugInAutoStartOriginHashesChanged(m_processPool); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/PlugInAutoStartProvider.h b/Source/WebKit2/UIProcess/Plugins/PlugInAutoStartProvider.h index c3b390272..fe6bc6f56 100644 --- a/Source/WebKit2/UIProcess/Plugins/PlugInAutoStartProvider.h +++ b/Source/WebKit2/UIProcess/Plugins/PlugInAutoStartProvider.h @@ -26,6 +26,7 @@ #ifndef PlugInAutoStartProvider_h #define PlugInAutoStartProvider_h +#include <WebCore/SessionID.h> #include <functional> #include <wtf/HashMap.h> #include <wtf/HashSet.h> @@ -36,41 +37,43 @@ namespace API { class Array; +class Dictionary; } namespace WebKit { -class ImmutableDictionary; -class WebContext; +class WebProcessPool; -typedef HashMap<unsigned, double> PlugInAutoStartOriginHash; +typedef HashMap<unsigned, double> PlugInAutoStartOriginMap; +typedef HashMap<WebCore::SessionID, PlugInAutoStartOriginMap> SessionPlugInAutoStartOriginMap; typedef Vector<String> PlugInAutoStartOrigins; class PlugInAutoStartProvider { WTF_MAKE_NONCOPYABLE(PlugInAutoStartProvider); public: - explicit PlugInAutoStartProvider(WebContext*); + explicit PlugInAutoStartProvider(WebProcessPool*); - void addAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash); - void didReceiveUserInteraction(unsigned plugInOriginHash); + void addAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash, WebCore::SessionID); + void didReceiveUserInteraction(unsigned plugInOriginHash, WebCore::SessionID); - PassRefPtr<ImmutableDictionary> autoStartOriginsTableCopy() const; - void setAutoStartOriginsTable(ImmutableDictionary&); - void setAutoStartOriginsFilteringOutEntriesAddedAfterTime(ImmutableDictionary&, double time); + Ref<API::Dictionary> autoStartOriginsTableCopy() const; + void setAutoStartOriginsTable(API::Dictionary&); + void setAutoStartOriginsFilteringOutEntriesAddedAfterTime(API::Dictionary&, double time); void setAutoStartOriginsArray(API::Array&); - PlugInAutoStartOriginHash autoStartOriginHashesCopy() const; + SessionPlugInAutoStartOriginMap autoStartOriginHashesCopy() const; const PlugInAutoStartOrigins& autoStartOrigins() const { return m_autoStartOrigins; } private: - WebContext* m_context; + WebProcessPool* m_processPool; - void setAutoStartOriginsTableWithItemsPassingTest(ImmutableDictionary&, std::function<bool(double expirationTimestamp)>); + void setAutoStartOriginsTableWithItemsPassingTest(API::Dictionary&, std::function<bool(double expirationTimestamp)>); - typedef HashMap<String, PlugInAutoStartOriginHash, CaseFoldingHash> AutoStartTable; - AutoStartTable m_autoStartTable; + typedef HashMap<String, PlugInAutoStartOriginMap, ASCIICaseInsensitiveHash> AutoStartTable; + typedef HashMap<WebCore::SessionID, AutoStartTable> SessionAutoStartTable; + SessionAutoStartTable m_autoStartTable; - HashMap<unsigned, String> m_hashToOriginMap; + HashMap<WebCore::SessionID, HashMap<unsigned, String>> m_hashToOriginMap; PlugInAutoStartOrigins m_autoStartOrigins; }; diff --git a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp index 0dde1a093..6079068bb 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp +++ b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp @@ -41,7 +41,6 @@ namespace WebKit { PluginInfoStore::PluginInfoStore() : m_pluginListIsUpToDate(false) - , m_client(0) { } @@ -68,7 +67,7 @@ void PluginInfoStore::loadPluginsIfNecessary() if (m_pluginListIsUpToDate) return; - ListHashSet<String, 32> uniquePluginPaths; + ListHashSet<String> uniquePluginPaths; // First, load plug-ins from the additional plug-ins directories specified. for (size_t i = 0; i < m_additionalPluginsDirectories.size(); ++i) @@ -88,9 +87,6 @@ void PluginInfoStore::loadPluginsIfNecessary() loadPlugin(m_plugins, pluginPath); m_pluginListIsUpToDate = true; - - if (m_client) - m_client->pluginInfoStoreDidLoadPlugins(this); } void PluginInfoStore::loadPlugin(Vector<PluginModuleInfo>& plugins, const String& pluginPath) @@ -115,15 +111,12 @@ Vector<PluginModuleInfo> PluginInfoStore::plugins() PluginModuleInfo PluginInfoStore::findPluginForMIMEType(const String& mimeType, PluginData::AllowedPluginTypes allowedPluginTypes) const { ASSERT(!mimeType.isNull()); - - for (size_t i = 0; i < m_plugins.size(); ++i) { - const PluginModuleInfo& plugin = m_plugins[i]; + for (const auto& plugin : m_plugins) { 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]; + + for (const auto& mimeClassInfo : plugin.info.mimes) { if (mimeClassInfo.type == mimeType) return plugin; } @@ -135,19 +128,13 @@ PluginModuleInfo PluginInfoStore::findPluginForMIMEType(const String& mimeType, PluginModuleInfo PluginInfoStore::findPluginForExtension(const String& extension, String& mimeType, PluginData::AllowedPluginTypes allowedPluginTypes) const { ASSERT(!extension.isNull()); - - for (size_t i = 0; i < m_plugins.size(); ++i) { - const PluginModuleInfo& plugin = m_plugins[i]; + for (const auto& plugin : m_plugins) { 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 (std::find(extensions.begin(), extensions.end(), extension) != extensions.end()) { + for (const auto& mimeClassInfo : plugin.info.mimes) { + if (mimeClassInfo.extensions.contains(extension)) { // We found a supported extension, set the correct MIME type. mimeType = mimeClassInfo.type; return plugin; @@ -163,15 +150,15 @@ static inline String pathExtension(const URL& url) String extension; String filename = url.lastPathComponent(); if (!filename.endsWith('/')) { - int extensionPos = filename.reverseFind('.'); - if (extensionPos != -1) + size_t extensionPos = filename.reverseFind('.'); + if (extensionPos != notFound) extension = filename.substring(extensionPos + 1); } - - return extension; + return extension.convertToASCIILowercase(); } -#if !PLATFORM(MAC) +#if !PLATFORM(COCOA) + PluginModuleLoadPolicy PluginInfoStore::defaultLoadPolicyForPlugin(const PluginModuleInfo&) { return PluginModuleLoadNormally; @@ -197,7 +184,7 @@ PluginModuleInfo PluginInfoStore::findPlugin(String& mimeType, const URL& url, P } // Next, check if any plug-ins claim to support the URL extension. - String extension = pathExtension(url).lower(); + String extension = pathExtension(url); if (!extension.isNull() && mimeType.isEmpty()) { PluginModuleInfo plugin = findPluginForExtension(extension, mimeType, allowedPluginTypes); if (!plugin.path.isNull()) @@ -219,11 +206,11 @@ PluginModuleInfo PluginInfoStore::findPlugin(String& mimeType, const URL& url, P 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]; + for (const auto& plugin : m_plugins) { + if (plugin.path == pluginPath) + return plugin; } - + ASSERT_NOT_REACHED(); return PluginModuleInfo(); } diff --git a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h index 7b4f509c7..2791c98f6 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h +++ b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,15 +40,6 @@ 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); @@ -73,9 +64,6 @@ public: static PluginModuleLoadPolicy defaultLoadPolicyForPlugin(const PluginModuleInfo&); - void setClient(PluginInfoStoreClient* client) { m_client = client; } - PluginInfoStoreClient* client() const { return m_client; } - private: PluginModuleInfo findPluginForMIMEType(const String& mimeType, WebCore::PluginData::AllowedPluginTypes) const; PluginModuleInfo findPluginForExtension(const String& extension, String& mimeType, WebCore::PluginData::AllowedPluginTypes) const; @@ -103,7 +91,6 @@ private: Vector<String> m_additionalPluginsDirectories; Vector<PluginModuleInfo> m_plugins; bool m_pluginListIsUpToDate; - PluginInfoStoreClient* m_client; }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp index 156fb6de4..6d0be9fdf 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp @@ -29,20 +29,22 @@ #if ENABLE(NETSCAPE_PLUGIN_API) #include "PluginProcessProxy.h" -#include "WebContext.h" #include <wtf/CryptographicallyRandomNumber.h> #include <wtf/StdLibExtras.h> #include <wtf/text/WTFString.h> namespace WebKit { -PluginProcessManager& PluginProcessManager::shared() +PluginProcessManager& PluginProcessManager::singleton() { static NeverDestroyed<PluginProcessManager> pluginProcessManager; return pluginProcessManager; } PluginProcessManager::PluginProcessManager() +#if PLATFORM(COCOA) + : m_processSuppressionDisabledForPageCounter([this](RefCounterEvent event) { updateProcessSuppressionDisabled(event); }) +#endif { } @@ -71,18 +73,18 @@ uint64_t PluginProcessManager::pluginProcessToken(const PluginModuleInfo& plugin attributes.processType = pluginProcessType; attributes.sandboxPolicy = pluginProcessSandboxPolicy; - m_pluginProcessTokens.append(std::make_pair(std::move(attributes), token)); + m_pluginProcessTokens.append(std::make_pair(WTFMove(attributes), token)); m_knownTokens.add(token); return token; } -void PluginProcessManager::getPluginProcessConnection(uint64_t pluginProcessToken, PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply) +void PluginProcessManager::getPluginProcessConnection(uint64_t pluginProcessToken, Ref<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply>&& reply) { ASSERT(pluginProcessToken); PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(pluginProcessToken); - pluginProcess->getPluginProcessConnection(reply); + pluginProcess->getPluginProcessConnection(WTFMove(reply)); } void PluginProcessManager::removePluginProcessProxy(PluginProcessProxy* pluginProcessProxy) @@ -93,16 +95,24 @@ void PluginProcessManager::removePluginProcessProxy(PluginProcessProxy* pluginPr m_pluginProcesses.remove(vectorIndex); } -void PluginProcessManager::getSitesWithData(const PluginModuleInfo& plugin, WebPluginSiteDataManager* webPluginSiteDataManager, uint64_t callbackID) +void PluginProcessManager::fetchWebsiteData(const PluginModuleInfo& plugin, std::function<void (Vector<String>)> completionHandler) { PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(pluginProcessToken(plugin, PluginProcessTypeNormal, PluginProcessSandboxPolicyNormal)); - pluginProcess->getSitesWithData(webPluginSiteDataManager, callbackID); + + pluginProcess->fetchWebsiteData(WTFMove(completionHandler)); +} + +void PluginProcessManager::deleteWebsiteData(const PluginModuleInfo& plugin, std::chrono::system_clock::time_point modifiedSince, std::function<void ()> completionHandler) +{ + PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(pluginProcessToken(plugin, PluginProcessTypeNormal, PluginProcessSandboxPolicyNormal)); + + pluginProcess->deleteWebsiteData(modifiedSince, WTFMove(completionHandler)); } -void PluginProcessManager::clearSiteData(const PluginModuleInfo& plugin, WebPluginSiteDataManager* webPluginSiteDataManager, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID) +void PluginProcessManager::deleteWebsiteDataForHostNames(const PluginModuleInfo& plugin, const Vector<String>& hostNames, std::function<void ()> completionHandler) { PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(pluginProcessToken(plugin, PluginProcessTypeNormal, PluginProcessSandboxPolicyNormal)); - pluginProcess->clearSiteData(webPluginSiteDataManager, sites, flags, maxAgeInSeconds, callbackID); + pluginProcess->deleteWebsiteDataForHostNames(hostNames, WTFMove(completionHandler)); } PluginProcessProxy* PluginProcessManager::getOrCreatePluginProcess(uint64_t pluginProcessToken) @@ -115,10 +125,10 @@ PluginProcessProxy* PluginProcessManager::getOrCreatePluginProcess(uint64_t plug 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(); + auto pluginProcess = PluginProcessProxy::create(this, attributesAndToken.first, attributesAndToken.second); + PluginProcessProxy* pluginProcessPtr = pluginProcess.ptr(); - m_pluginProcesses.append(pluginProcess.release()); + m_pluginProcesses.append(WTFMove(pluginProcess)); return pluginProcessPtr; } } diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h index 0c59a764a..dd44d622c 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h @@ -31,15 +31,17 @@ #include "PluginModuleInfo.h" #include "PluginProcess.h" #include "PluginProcessAttributes.h" +#include "ProcessThrottler.h" #include "WebProcessProxyMessages.h" #include <wtf/Forward.h> #include <wtf/HashSet.h> #include <wtf/NeverDestroyed.h> #include <wtf/Noncopyable.h> +#include <wtf/RefCounter.h> #include <wtf/Vector.h> namespace IPC { - class ArgumentEncoder; +class Encoder; } namespace WebKit { @@ -47,24 +49,26 @@ namespace WebKit { class PluginInfoStore; class PluginProcessProxy; class WebProcessProxy; -class WebPluginSiteDataManager; class PluginProcessManager { WTF_MAKE_NONCOPYABLE(PluginProcessManager); friend class NeverDestroyed<PluginProcessManager>; public: - static PluginProcessManager& shared(); + static PluginProcessManager& singleton(); uint64_t pluginProcessToken(const PluginModuleInfo&, PluginProcessType, PluginProcessSandboxPolicy); - void getPluginProcessConnection(uint64_t pluginProcessToken, PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply>); + void getPluginProcessConnection(uint64_t pluginProcessToken, Ref<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 fetchWebsiteData(const PluginModuleInfo&, std::function<void (Vector<String>)> completionHandler); + void deleteWebsiteData(const PluginModuleInfo&, std::chrono::system_clock::time_point modifiedSince, std::function<void ()> completionHandler); + void deleteWebsiteDataForHostNames(const PluginModuleInfo&, const Vector<String>& hostNames, std::function<void ()> completionHandler); -#if PLATFORM(MAC) - void setProcessSuppressionEnabled(bool); +#if PLATFORM(COCOA) + inline ProcessSuppressionDisabledToken processSuppressionDisabledToken(); + inline bool processSuppressionDisabled() const; + void updateProcessSuppressionDisabled(RefCounterEvent); #endif private: @@ -76,8 +80,24 @@ private: HashSet<uint64_t> m_knownTokens; Vector<RefPtr<PluginProcessProxy>> m_pluginProcesses; + +#if PLATFORM(COCOA) + ProcessSuppressionDisabledCounter m_processSuppressionDisabledForPageCounter; +#endif }; +#if PLATFORM(COCOA) +inline ProcessSuppressionDisabledToken PluginProcessManager::processSuppressionDisabledToken() +{ + return m_processSuppressionDisabledForPageCounter.count(); +} + +inline bool PluginProcessManager::processSuppressionDisabled() const +{ + return m_processSuppressionDisabledForPageCounter.value(); +} +#endif + } // namespace WebKit #endif // ENABLE(NETSCAPE_PLUGIN_API) diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp index 27772f561..5ff51b509 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp @@ -32,15 +32,14 @@ #include "PluginProcessCreationParameters.h" #include "PluginProcessManager.h" #include "PluginProcessMessages.h" -#include "WebContext.h" #include "WebCoreArgumentCoders.h" -#include "WebPluginSiteDataManager.h" +#include "WebProcessPool.h" #include "WebProcessProxy.h" #include <WebCore/NotImplemented.h> #include <wtf/RunLoop.h> -#if PLATFORM(MAC) -#include "MachPort.h" +#if OS(LINUX) +#include "MemoryPressureMonitor.h" #endif using namespace WebCore; @@ -53,9 +52,16 @@ static const double snapshottingMinimumLifetime = 30; static const double shutdownTimeout = 1 * 60; static const double snapshottingShutdownTimeout = 15; -PassRefPtr<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginProcessAttributes& pluginProcessAttributes, uint64_t pluginProcessToken) +static uint64_t generateCallbackID() { - return adoptRef(new PluginProcessProxy(PluginProcessManager, pluginProcessAttributes, pluginProcessToken)); + static uint64_t callbackID; + + return ++callbackID; +} + +Ref<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginProcessAttributes& pluginProcessAttributes, uint64_t pluginProcessToken) +{ + return adoptRef(*new PluginProcessProxy(PluginProcessManager, pluginProcessAttributes, pluginProcessToken)); } PluginProcessProxy::PluginProcessProxy(PluginProcessManager* PluginProcessManager, const PluginProcessAttributes& pluginProcessAttributes, uint64_t pluginProcessToken) @@ -63,7 +69,7 @@ PluginProcessProxy::PluginProcessProxy(PluginProcessManager* PluginProcessManage , m_pluginProcessAttributes(pluginProcessAttributes) , m_pluginProcessToken(pluginProcessToken) , m_numPendingConnectionRequests(0) -#if PLATFORM(MAC) +#if PLATFORM(COCOA) , m_modalWindowIsShowing(false) , m_fullscreenWindowIsShowing(false) , m_preFullscreenAppPresentationOptions(0) @@ -74,61 +80,76 @@ PluginProcessProxy::PluginProcessProxy(PluginProcessManager* PluginProcessManage PluginProcessProxy::~PluginProcessProxy() { + ASSERT(m_pendingFetchWebsiteDataRequests.isEmpty()); + ASSERT(m_pendingFetchWebsiteDataCallbacks.isEmpty()); + ASSERT(m_pendingDeleteWebsiteDataRequests.isEmpty()); + ASSERT(m_pendingDeleteWebsiteDataCallbacks.isEmpty()); } void PluginProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions) { - launchOptions.processType = ProcessLauncher::PluginProcess; + ChildProcessProxy::getLaunchOptions(launchOptions); platformGetLaunchOptions(launchOptions, m_pluginProcessAttributes); } +void PluginProcessProxy::processWillShutDown(IPC::Connection& connection) +{ + ASSERT_UNUSED(connection, this->connection() == &connection); +} + // 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) +void PluginProcessProxy::getPluginProcessConnection(Ref<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply>&& reply) { - m_pendingConnectionReplies.append(reply); + m_pendingConnectionReplies.append(WTFMove(reply)); - if (isLaunching()) { + if (state() == State::Launching) { 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, IPC::DispatchMessageEvenWhenWaitingForSyncReply); + m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0, IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply); } -void PluginProcessProxy::getSitesWithData(WebPluginSiteDataManager* webPluginSiteDataManager, uint64_t callbackID) +void PluginProcessProxy::fetchWebsiteData(std::function<void (Vector<String>)> completionHandler) { - ASSERT(!m_pendingGetSitesReplies.contains(callbackID)); - m_pendingGetSitesReplies.set(callbackID, webPluginSiteDataManager); + uint64_t callbackID = generateCallbackID(); + m_pendingFetchWebsiteDataCallbacks.set(callbackID, WTFMove(completionHandler)); - if (isLaunching()) { - m_pendingGetSitesRequests.append(callbackID); + if (state() == State::Launching) { + m_pendingFetchWebsiteDataRequests.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) +void PluginProcessProxy::deleteWebsiteData(std::chrono::system_clock::time_point modifiedSince, std::function<void ()> completionHandler) +{ + uint64_t callbackID = generateCallbackID(); + m_pendingDeleteWebsiteDataCallbacks.set(callbackID, WTFMove(completionHandler)); + + if (state() == State::Launching) { + m_pendingDeleteWebsiteDataRequests.append({ modifiedSince, callbackID }); + return; + } + + m_connection->send(Messages::PluginProcess::DeleteWebsiteData(modifiedSince, callbackID), 0); +} + +void PluginProcessProxy::deleteWebsiteDataForHostNames(const Vector<String>& hostNames, std::function<void ()> completionHandler) { - ASSERT(!m_pendingClearSiteDataReplies.contains(callbackID)); - m_pendingClearSiteDataReplies.set(callbackID, webPluginSiteDataManager); - - if (isLaunching()) { - ClearSiteDataRequest request; - request.sites = sites; - request.flags = flags; - request.maxAgeInSeconds = maxAgeInSeconds; - request.callbackID = callbackID; - m_pendingClearSiteDataRequests.append(request); + uint64_t callbackID = generateCallbackID(); + m_pendingDeleteWebsiteDataForHostNamesCallbacks.set(callbackID, WTFMove(completionHandler)); + + if (state() == State::Launching) { + m_pendingDeleteWebsiteDataForHostNamesRequests.append({ hostNames, callbackID }); return; } - // Ask the plug-in process to clear the site data. - m_connection->send(Messages::PluginProcess::ClearSiteData(sites, flags, maxAgeInSeconds, callbackID), 0); + m_connection->send(Messages::PluginProcess::DeleteWebsiteDataForHostNames(hostNames, callbackID), 0); } void PluginProcessProxy::pluginProcessCrashedOrFailedToLaunch() @@ -137,28 +158,37 @@ void PluginProcessProxy::pluginProcessCrashedOrFailedToLaunch() while (!m_pendingConnectionReplies.isEmpty()) { RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply = m_pendingConnectionReplies.takeFirst(); -#if PLATFORM(MAC) - reply->send(IPC::Attachment(0, MACH_MSG_TYPE_MOVE_SEND), false); -#elif USE(UNIX_DOMAIN_SOCKETS) +#if USE(UNIX_DOMAIN_SOCKETS) reply->send(IPC::Attachment(), false); +#elif OS(DARWIN) + reply->send(IPC::Attachment(0, MACH_MSG_TYPE_MOVE_SEND), false); #else notImplemented(); #endif } - while (!m_pendingGetSitesReplies.isEmpty()) - didGetSitesWithData(Vector<String>(), m_pendingGetSitesReplies.begin()->key); + m_pendingFetchWebsiteDataRequests.clear(); + for (const auto& callback : m_pendingFetchWebsiteDataCallbacks.values()) + callback({ }); + m_pendingFetchWebsiteDataCallbacks.clear(); + + m_pendingDeleteWebsiteDataRequests.clear(); + for (const auto& callback : m_pendingDeleteWebsiteDataCallbacks.values()) + callback(); + m_pendingDeleteWebsiteDataRequests.clear(); - while (!m_pendingClearSiteDataReplies.isEmpty()) - didClearSiteData(m_pendingClearSiteDataReplies.begin()->key); + m_pendingDeleteWebsiteDataForHostNamesRequests.clear(); + for (const auto& callback : m_pendingDeleteWebsiteDataForHostNamesCallbacks.values()) + callback(); + m_pendingDeleteWebsiteDataForHostNamesCallbacks.clear(); // Tell the plug-in process manager to forget about this plug-in process proxy. This may cause us to be deleted. m_pluginProcessManager->removePluginProcessProxy(this); } -void PluginProcessProxy::didClose(IPC::Connection*) +void PluginProcessProxy::didClose(IPC::Connection&) { -#if PLATFORM(MAC) +#if PLATFORM(COCOA) if (m_modalWindowIsShowing) endModal(); @@ -166,15 +196,15 @@ void PluginProcessProxy::didClose(IPC::Connection*) exitFullscreen(); #endif - const Vector<WebContext*>& contexts = WebContext::allContexts(); - for (size_t i = 0; i < contexts.size(); ++i) - contexts[i]->sendToAllProcesses(Messages::PluginProcessConnectionManager::PluginProcessCrashed(m_pluginProcessToken)); + const Vector<WebProcessPool*>& processPools = WebProcessPool::allProcessPools(); + for (size_t i = 0; i < processPools.size(); ++i) + processPools[i]->sendToAllProcesses(Messages::PluginProcessConnectionManager::PluginProcessCrashed(m_pluginProcessToken)); // This will cause us to be deleted. pluginProcessCrashedOrFailedToLaunch(); } -void PluginProcessProxy::didReceiveInvalidMessage(IPC::Connection*, IPC::StringReference, IPC::StringReference) +void PluginProcessProxy::didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference, IPC::StringReference) { } @@ -187,8 +217,8 @@ void PluginProcessProxy::didFinishLaunching(ProcessLauncher*, IPC::Connection::I return; } - m_connection = IPC::Connection::createServerConnection(connectionIdentifier, this, RunLoop::main()); -#if PLATFORM(MAC) + m_connection = IPC::Connection::createServerConnection(connectionIdentifier, *this); +#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED <= 101000 m_connection->setShouldCloseConnectionOnMachExceptions(); #endif @@ -203,33 +233,40 @@ void PluginProcessProxy::didFinishLaunching(ProcessLauncher*, IPC::Connection::I parameters.minimumLifetime = minimumLifetime; parameters.terminationTimeout = shutdownTimeout; } + +#if OS(LINUX) + if (MemoryPressureMonitor::isEnabled()) + parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle(); +#endif + platformInitializePluginProcess(parameters); // Initialize the plug-in host process. m_connection->send(Messages::PluginProcess::InitializePluginProcess(parameters), 0); -#if PLATFORM(MAC) +#if PLATFORM(COCOA) m_connection->send(Messages::PluginProcess::SetQOS(pluginProcessLatencyQOS(), pluginProcessThroughputQOS()), 0); #endif - // 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 (auto callbackID : m_pendingFetchWebsiteDataRequests) + m_connection->send(Messages::PluginProcess::GetSitesWithData(callbackID), 0); + m_pendingFetchWebsiteDataRequests.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 (auto& request : m_pendingDeleteWebsiteDataRequests) + m_connection->send(Messages::PluginProcess::DeleteWebsiteData(request.modifiedSince, request.callbackID), 0); + m_pendingDeleteWebsiteDataRequests.clear(); + + for (auto& request : m_pendingDeleteWebsiteDataForHostNamesRequests) + m_connection->send(Messages::PluginProcess::DeleteWebsiteDataForHostNames(request.hostNames, request.callbackID), 0); + m_pendingDeleteWebsiteDataForHostNamesRequests.clear(); for (unsigned i = 0; i < m_numPendingConnectionRequests; ++i) m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0); m_numPendingConnectionRequests = 0; -#if PLATFORM(MAC) - if (WebContext::processSuppressionIsEnabledForAllContexts()) +#if PLATFORM(COCOA) + if (!PluginProcessManager::singleton().processSuppressionDisabled()) setProcessSuppressionEnabled(true); #endif } @@ -241,10 +278,10 @@ void PluginProcessProxy::didCreateWebProcessConnection(const IPC::Attachment& co // Grab the first pending connection reply. RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply = m_pendingConnectionReplies.takeFirst(); -#if PLATFORM(MAC) - reply->send(IPC::Attachment(connectionIdentifier.port(), MACH_MSG_TYPE_MOVE_SEND), supportsAsynchronousPluginInitialization); -#elif USE(UNIX_DOMAIN_SOCKETS) +#if USE(UNIX_DOMAIN_SOCKETS) reply->send(connectionIdentifier, supportsAsynchronousPluginInitialization); +#elif OS(DARWIN) + reply->send(IPC::Attachment(connectionIdentifier.port(), MACH_MSG_TYPE_MOVE_SEND), supportsAsynchronousPluginInitialization); #else notImplemented(); #endif @@ -252,18 +289,20 @@ void PluginProcessProxy::didCreateWebProcessConnection(const IPC::Attachment& co void PluginProcessProxy::didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID) { - RefPtr<WebPluginSiteDataManager> webPluginSiteDataManager = m_pendingGetSitesReplies.take(callbackID); - ASSERT(webPluginSiteDataManager); + auto callback = m_pendingFetchWebsiteDataCallbacks.take(callbackID); + callback(sites); +} - webPluginSiteDataManager->didGetSitesWithDataForSinglePlugin(sites, callbackID); +void PluginProcessProxy::didDeleteWebsiteData(uint64_t callbackID) +{ + auto callback = m_pendingDeleteWebsiteDataCallbacks.take(callbackID); + callback(); } -void PluginProcessProxy::didClearSiteData(uint64_t callbackID) +void PluginProcessProxy::didDeleteWebsiteDataForHostNames(uint64_t callbackID) { - RefPtr<WebPluginSiteDataManager> webPluginSiteDataManager = m_pendingClearSiteDataReplies.take(callbackID); - ASSERT(webPluginSiteDataManager); - - webPluginSiteDataManager->didClearSiteDataForSinglePlugin(callbackID); + auto callback = m_pendingDeleteWebsiteDataForHostNamesCallbacks.take(callbackID); + callback(); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h index 484a20c29..ef43eabb0 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h @@ -37,21 +37,15 @@ #include "WebProcessProxyMessages.h" #include <wtf/Deque.h> -#if PLATFORM(MAC) +#if PLATFORM(COCOA) #include <wtf/RetainPtr.h> OBJC_CLASS NSObject; OBJC_CLASS WKPlaceholderModalWindow; #endif -// FIXME: This is platform specific. -namespace IPC { - class MachPort; -} - namespace WebKit { class PluginProcessManager; -class WebPluginSiteDataManager; class WebProcessProxy; struct PluginProcessCreationParameters; @@ -60,17 +54,21 @@ struct RawPluginMetaData { String name; String description; String mimeDescription; + +#if PLATFORM(GTK) + bool requiresGtk2; +#endif }; #endif -#if PLATFORM(MAC) +#if PLATFORM(COCOA) int pluginProcessLatencyQOS(); int pluginProcessThroughputQOS(); #endif class PluginProcessProxy : public ChildProcessProxy { public: - static PassRefPtr<PluginProcessProxy> create(PluginProcessManager*, const PluginProcessAttributes&, uint64_t pluginProcessToken); + static Ref<PluginProcessProxy> create(PluginProcessManager*, const PluginProcessAttributes&, uint64_t pluginProcessToken); ~PluginProcessProxy(); const PluginProcessAttributes& pluginProcessAttributes() const { return m_pluginProcessAttributes; } @@ -78,26 +76,24 @@ public: // 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); + void getPluginProcessConnection(Ref<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply>&&); - // 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); + void fetchWebsiteData(std::function<void (Vector<String>)> completionHandler); + void deleteWebsiteData(std::chrono::system_clock::time_point modifiedSince, std::function<void ()> completionHandler); + void deleteWebsiteDataForHostNames(const Vector<String>& hostNames, std::function<void ()> completionHandler); bool isValid() const { return m_connection; } -#if PLATFORM(MAC) +#if PLATFORM(COCOA) void setProcessSuppressionEnabled(bool); - // Returns whether the plug-in needs the heap to be marked executable. - static bool pluginNeedsExecutableHeap(const PluginModuleInfo&); - +#if __MAC_OS_X_VERSION_MIN_REQUIRED <= 101000 // Creates a property list in ~/Library/Preferences that contains all the MIME types supported by the plug-in. static bool createPropertyListFile(const PluginModuleInfo&); #endif +#endif + #if PLUGIN_ARCHITECTURE(X11) static bool scanPlugin(const String& pluginPath, RawPluginMetaData& result); #endif @@ -105,27 +101,29 @@ public: private: PluginProcessProxy(PluginProcessManager*, const PluginProcessAttributes&, uint64_t pluginProcessToken); - virtual void getLaunchOptions(ProcessLauncher::LaunchOptions&) override; + void getLaunchOptions(ProcessLauncher::LaunchOptions&) override; void platformGetLaunchOptions(ProcessLauncher::LaunchOptions&, const PluginProcessAttributes&); + void processWillShutDown(IPC::Connection&) override; void pluginProcessCrashedOrFailedToLaunch(); // IPC::Connection::Client - virtual void didReceiveMessage(IPC::Connection*, IPC::MessageDecoder&) override; - virtual void didReceiveSyncMessage(IPC::Connection*, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&) override; + void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override; + void didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>&) override; - virtual void didClose(IPC::Connection*) override; - virtual void didReceiveInvalidMessage(IPC::Connection*, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override; + void didClose(IPC::Connection&) override; + void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override; // ProcessLauncher::Client - virtual void didFinishLaunching(ProcessLauncher*, IPC::Connection::Identifier); + void didFinishLaunching(ProcessLauncher*, IPC::Connection::Identifier) override; // Message handlers void didCreateWebProcessConnection(const IPC::Attachment&, bool supportsAsynchronousPluginInitialization); void didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID); - void didClearSiteData(uint64_t callbackID); + void didDeleteWebsiteData(uint64_t callbackID); + void didDeleteWebsiteDataForHostNames(uint64_t callbackID); -#if PLATFORM(MAC) +#if PLATFORM(COCOA) bool getPluginProcessSerialNumber(ProcessSerialNumber&); void makePluginProcessTheFrontProcess(); void makeUIProcessTheFrontProcess(); @@ -139,7 +137,6 @@ 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); @@ -159,23 +156,28 @@ private: Deque<RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply>> m_pendingConnectionReplies; - Vector<uint64_t> m_pendingGetSitesRequests; - HashMap<uint64_t, RefPtr<WebPluginSiteDataManager>> m_pendingGetSitesReplies; + Vector<uint64_t> m_pendingFetchWebsiteDataRequests; + HashMap<uint64_t, std::function<void (Vector<String>)>> m_pendingFetchWebsiteDataCallbacks; + + struct DeleteWebsiteDataRequest { + std::chrono::system_clock::time_point modifiedSince; + uint64_t callbackID; + }; + Vector<DeleteWebsiteDataRequest> m_pendingDeleteWebsiteDataRequests; + HashMap<uint64_t, std::function<void ()>> m_pendingDeleteWebsiteDataCallbacks; - struct ClearSiteDataRequest { - Vector<String> sites; - uint64_t flags; - uint64_t maxAgeInSeconds; + struct DeleteWebsiteDataForHostNamesRequest { + Vector<String> hostNames; uint64_t callbackID; }; - Vector<ClearSiteDataRequest> m_pendingClearSiteDataRequests; - HashMap<uint64_t, RefPtr<WebPluginSiteDataManager>> m_pendingClearSiteDataReplies; + Vector<DeleteWebsiteDataForHostNamesRequest> m_pendingDeleteWebsiteDataForHostNamesRequests; + HashMap<uint64_t, std::function<void ()>> m_pendingDeleteWebsiteDataForHostNamesCallbacks; // 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) +#if PLATFORM(COCOA) RetainPtr<NSObject> m_activationObserver; RetainPtr<WKPlaceholderModalWindow *> m_placeholderWindow; bool m_modalWindowIsShowing; diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in index 25afc5d67..e18e55eb0 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.messages.in @@ -26,15 +26,13 @@ messages -> PluginProcessProxy { DidCreateWebProcessConnection(IPC::Attachment connectionIdentifier, bool supportsAsynchronousPluginInitialization) DidGetSitesWithData(Vector<String> sites, uint64_t callbackID) - DidClearSiteData(uint64_t callbackID) + DidDeleteWebsiteData(uint64_t callbackID) + DidDeleteWebsiteDataForHostNames(uint64_t callbackID) -#if PLATFORM(MAC) +#if PLATFORM(COCOA) 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(String launchPath, Vector<String> arguments) -> (bool result) diff --git a/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp b/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp deleted file mode 100644 index acfa80241..000000000 --- a/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (C) 2011, 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. - */ - -#include "config.h" -#include "WebPluginSiteDataManager.h" - -#if ENABLE(NETSCAPE_PLUGIN_API) - -#include "APIArray.h" -#include "PluginProcessManager.h" -#include "WebContext.h" -#include "WebProcessMessages.h" - -using namespace WebCore; - -namespace WebKit { - -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; -}; - -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()); - ASSERT(m_pendingGetSitesWithData.isEmpty()); - ASSERT(m_pendingClearSiteData.isEmpty()); -} - -void WebPluginSiteDataManager::invalidate() -{ - invalidateCallbackMap(m_arrayCallbacks); - - m_pendingGetSitesWithData.clear(); - m_pendingClearSiteData.clear(); -} - -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()); - - ASSERT(!m_pendingGetSitesWithData.contains(callbackID)); - - GetSitesWithDataState* state = new GetSitesWithDataState(this, callbackID); - m_pendingGetSitesWithData.set(callbackID, adoptPtr(state)); - state->getSitesWithDataForNextPlugin(); -} - -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; - } - - callback->performCallbackWithReturnValue(API::Array::createStringArray(sites).get()); -} - -void WebPluginSiteDataManager::clearSiteData(API::Array* 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 (API::String* site = sites->at<API::String>(i)) - sitesVector.append(site->string()); - } - } - - uint64_t callbackID = callback->callbackID(); - m_voidCallbacks.set(callbackID, callback.release()); - - ASSERT(!m_pendingClearSiteData.contains(callbackID)); - - ClearSiteDataState* state = new ClearSiteDataState(this, sitesVector, flags, maxAgeInSeconds, callbackID); - m_pendingClearSiteData.set(callbackID, adoptPtr(state)); - state->clearSiteDataForNextPlugin(); -} - -void WebPluginSiteDataManager::didClearSiteData(uint64_t callbackID) -{ - RefPtr<VoidCallback> callback = m_voidCallbacks.take(callbackID); - if (!callback) { - // FIXME: Log error or assert. - return; - } - - callback->performCallback(); -} - -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 = 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 = m_pendingClearSiteData.take(callbackID); - ASSERT(state); - - didClearSiteData(callbackID); -} - -} // namespace WebKit - -#endif // ENABLE(NETSCAPE_PLUGIN_API) diff --git a/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.h b/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.h deleted file mode 100644 index f6918f959..000000000 --- a/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2011, 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 WebPluginSiteDataManager_h -#define WebPluginSiteDataManager_h - -#if ENABLE(NETSCAPE_PLUGIN_API) - -#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 API::ObjectImpl<API::Object::Type::PluginSiteDataManager> { -public: - 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(API::Array* sites, uint64_t flags, uint64_t maxAgeInSeconds, PassRefPtr<VoidCallback>); - void didClearSiteData(uint64_t callbackID); - - void didGetSitesWithDataForSinglePlugin(const Vector<String>& sites, uint64_t callbackID); - void didClearSiteDataForSinglePlugin(uint64_t callbackID); - -private: - explicit WebPluginSiteDataManager(WebContext*); - - WebContext* m_webContext; - HashMap<uint64_t, RefPtr<ArrayCallback>> m_arrayCallbacks; - HashMap<uint64_t, RefPtr<VoidCallback>> m_voidCallbacks; - - void didGetSitesWithDataForAllPlugins(const Vector<String>& sites, uint64_t callbackID); - void didClearSiteDataForAllPlugins(uint64_t callbackID); - - class GetSitesWithDataState; - HashMap<uint64_t, OwnPtr<GetSitesWithDataState>> m_pendingGetSitesWithData; - - class ClearSiteDataState; - HashMap<uint64_t, OwnPtr<ClearSiteDataState>> m_pendingClearSiteData; -}; - -} // namespace WebKit - -#endif // ENABLE(NETSCAPE_PLUGIN_API) - -#endif // WebPluginSiteDataManager_h diff --git a/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.cpp b/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.cpp index c6e46524d..3e1c2ef5a 100644 --- a/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.cpp +++ b/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.cpp @@ -30,26 +30,48 @@ #include "NetscapePluginModule.h" #include <WebCore/FileSystem.h> +#include <WebCore/PlatformDisplay.h> #include <wtf/text/CString.h> namespace WebKit { -static const unsigned gSchemaVersion = 1; +static const unsigned gSchemaVersion = 3; -PluginInfoCache& PluginInfoCache::shared() +PluginInfoCache& PluginInfoCache::singleton() { static NeverDestroyed<PluginInfoCache> pluginInfoCache; return pluginInfoCache; } +static inline const char* cacheFilenameForCurrentDisplay() +{ +#if PLATFORM(X11) + if (WebCore::PlatformDisplay::sharedDisplay().type() == WebCore::PlatformDisplay::Type::X11) + return "plugins-x11"; +#endif +#if PLATFORM(WAYLAND) + if (WebCore::PlatformDisplay::sharedDisplay().type() == WebCore::PlatformDisplay::Type::Wayland) + return "plugins-wayland"; +#endif + + ASSERT_NOT_REACHED(); + return "plugins"; +} + PluginInfoCache::PluginInfoCache() : m_cacheFile(g_key_file_new()) - , m_saveToFileIdleId(0) + , m_saveToFileIdle(RunLoop::main(), this, &PluginInfoCache::saveToFile) , m_readOnlyMode(false) { + m_saveToFileIdle.setPriority(G_PRIORITY_DEFAULT_IDLE); + GUniquePtr<char> cacheDirectory(g_build_filename(g_get_user_cache_dir(), "webkitgtk", nullptr)); if (WebCore::makeAllDirectories(cacheDirectory.get())) { - m_cachePath.reset(g_build_filename(cacheDirectory.get(), "plugins", nullptr)); + // Delete old cache file. + GUniquePtr<char> oldCachePath(g_build_filename(cacheDirectory.get(), "plugins", nullptr)); + WebCore::deleteFile(WebCore::stringFromFileSystemRepresentation(oldCachePath.get())); + + m_cachePath.reset(g_build_filename(cacheDirectory.get(), cacheFilenameForCurrentDisplay(), nullptr)); g_key_file_load_from_file(m_cacheFile.get(), m_cachePath.get(), G_KEY_FILE_NONE, nullptr); } @@ -72,23 +94,10 @@ PluginInfoCache::PluginInfoCache() PluginInfoCache::~PluginInfoCache() { - if (m_saveToFileIdleId) { - g_source_remove(m_saveToFileIdleId); - saveToFile(); - } -} - -gboolean PluginInfoCache::saveToFileIdleCallback(PluginInfoCache* cache) -{ - cache->saveToFile(); - return FALSE; } void PluginInfoCache::saveToFile() { - std::lock_guard<std::mutex> lock(m_mutex); - m_saveToFileIdleId = 0; - gsize dataLength; GUniquePtr<char> data(g_key_file_to_data(m_cacheFile.get(), &dataLength, nullptr)); if (!data) @@ -124,6 +133,8 @@ bool PluginInfoCache::getPluginInfo(const String& pluginPath, PluginModuleInfo& NetscapePluginModule::parseMIMEDescription(String::fromUTF8(stringValue.get()), plugin.info.mimes); #endif + plugin.requiresGtk2 = g_key_file_get_boolean(m_cacheFile.get(), pluginGroup.data(), "requires-gtk2", nullptr); + return true; } @@ -143,14 +154,15 @@ void PluginInfoCache::updatePluginInfo(const String& pluginPath, const PluginMod g_key_file_set_string(m_cacheFile.get(), pluginGroup.data(), "mime-description", mimeDescription.utf8().data()); #endif + g_key_file_set_boolean(m_cacheFile.get(), pluginGroup.data(), "requires-gtk2", plugin.requiresGtk2); + if (m_cachePath && !m_readOnlyMode) { // Save the cache file in an idle to make sure it happens in the main thread and // it's done only once when this is called multiple times in a very short time. - std::lock_guard<std::mutex> lock(m_mutex); - if (m_saveToFileIdleId) + if (m_saveToFileIdle.isActive()) return; - m_saveToFileIdleId = g_idle_add(reinterpret_cast<GSourceFunc>(PluginInfoCache::saveToFileIdleCallback), this); + m_saveToFileIdle.startOneShot(0); } } diff --git a/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.h b/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.h index 872f1eb01..1af7085e2 100644 --- a/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.h +++ b/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.h @@ -29,9 +29,9 @@ #if ENABLE(NETSCAPE_PLUGIN_API) #include "PluginModuleInfo.h" -#include <mutex> #include <wtf/NeverDestroyed.h> -#include <wtf/gobject/GUniquePtr.h> +#include <wtf/RunLoop.h> +#include <wtf/glib/GUniquePtr.h> namespace WebKit { @@ -39,7 +39,7 @@ class PluginInfoCache { WTF_MAKE_NONCOPYABLE(PluginInfoCache); friend class NeverDestroyed<PluginInfoCache>; public: - static PluginInfoCache& shared(); + static PluginInfoCache& singleton(); bool getPluginInfo(const String& pluginPath, PluginModuleInfo&); void updatePluginInfo(const String& pluginPath, const PluginModuleInfo&); @@ -49,13 +49,11 @@ private: ~PluginInfoCache(); void saveToFile(); - static gboolean saveToFileIdleCallback(PluginInfoCache*); GUniquePtr<GKeyFile> m_cacheFile; GUniquePtr<char> m_cachePath; - unsigned m_saveToFileIdleId; + RunLoop::Timer<PluginInfoCache> m_saveToFileIdle; bool m_readOnlyMode; - std::mutex m_mutex; }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp b/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp index a9685618f..3b7ef381a 100644 --- a/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp +++ b/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp @@ -32,8 +32,12 @@ #include "PluginInfoStore.h" #include "NetscapePluginModule.h" -#include "PluginDatabase.h" +#include "PluginSearchPath.h" +#include "ProcessExecutablePath.h" #include <WebCore/FileSystem.h> +#include <WebCore/PlatformDisplay.h> +#include <limits.h> +#include <stdlib.h> #if PLATFORM(GTK) #include "PluginInfoCache.h" @@ -45,51 +49,17 @@ 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.appendVector(paths); - } - - return result; + return WebKit::pluginsDirectories(); } 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); + char normalizedPath[PATH_MAX]; + for (const auto& path : listDirectory(directory, String("*.so"))) { + CString filename = fileSystemRepresentation(path); + if (realpath(filename.data(), normalizedPath)) + result.append(stringFromFileSystemRepresentation(normalizedPath)); } return result; @@ -103,11 +73,22 @@ Vector<String> PluginInfoStore::individualPluginPaths() bool PluginInfoStore::getPluginInfo(const String& pluginPath, PluginModuleInfo& plugin) { #if PLATFORM(GTK) - if (PluginInfoCache::shared().getPluginInfo(pluginPath, plugin)) + if (PluginInfoCache::singleton().getPluginInfo(pluginPath, plugin)) { +#if ENABLE(PLUGIN_PROCESS_GTK2) + if (plugin.requiresGtk2) { + if (PlatformDisplay::sharedDisplay().type() != PlatformDisplay::Type::X11) + return false; + String pluginProcessPath = executablePathOfPluginProcess(); + pluginProcessPath.append('2'); + if (!fileExists(pluginProcessPath)) + return false; + } +#endif return true; + } if (NetscapePluginModule::getPluginInfo(pluginPath, plugin)) { - PluginInfoCache::shared().updatePluginInfo(pluginPath, plugin); + PluginInfoCache::singleton().updatePluginInfo(pluginPath, plugin); return true; } return false; diff --git a/Source/WebKit2/UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp b/Source/WebKit2/UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp index 18e15864f..7601f4313 100644 --- a/Source/WebKit2/UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp +++ b/Source/WebKit2/UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Igalia S.L. + * Copyright (C) 2011, 2014 Igalia S.L. * Copyright (C) 2011 Apple Inc. * Copyright (C) 2012 Samsung Electronics * @@ -33,14 +33,19 @@ #include "PluginProcessCreationParameters.h" #include "ProcessExecutablePath.h" #include <WebCore/FileSystem.h> +#include <WebCore/PlatformDisplay.h> +#include <sys/wait.h> #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> -#if PLATFORM(GTK) || PLATFORM(EFL) + +#if PLATFORM(GTK) #include <glib.h> -#include <wtf/gobject/GUniquePtr.h> +#include <wtf/glib/GUniquePtr.h> #endif -#include <sys/wait.h> +#if PLATFORM(GTK) +#include "Module.h" +#endif using namespace WebCore; @@ -48,33 +53,57 @@ namespace WebKit { 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); -#endif + launchOptions.processType = ProcessLauncher::ProcessType::Plugin64; launchOptions.extraInitializationData.add("plugin-path", pluginProcessAttributes.moduleInfo.path); +#if PLATFORM(GTK) + if (pluginProcessAttributes.moduleInfo.requiresGtk2) + launchOptions.extraInitializationData.add("requires-gtk2", emptyString()); +#endif } void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationParameters&) { } +#if PLATFORM(GTK) +static bool pluginRequiresGtk2(const String& pluginPath) +{ + std::unique_ptr<Module> module = std::make_unique<Module>(pluginPath); + if (!module->load()) + return false; + return module->functionPointer<gpointer>("gtk_object_get_type"); +} +#endif + #if PLUGIN_ARCHITECTURE(X11) bool PluginProcessProxy::scanPlugin(const String& pluginPath, RawPluginMetaData& result) { -#if PLATFORM(GTK) || PLATFORM(EFL) - CString binaryPath = fileSystemRepresentation(executablePathOfPluginProcess()); +#if PLATFORM(GTK) + String pluginProcessPath = executablePathOfPluginProcess(); + +#if PLATFORM(GTK) + bool requiresGtk2 = pluginRequiresGtk2(pluginPath); + if (requiresGtk2) { + if (PlatformDisplay::sharedDisplay().type() != PlatformDisplay::Type::X11) + return false; +#if ENABLE(PLUGIN_PROCESS_GTK2) + pluginProcessPath.append('2'); + if (!fileExists(pluginProcessPath)) + return false; +#else + return false; +#endif + } +#endif + + CString binaryPath = fileSystemRepresentation(pluginProcessPath); CString pluginPathCString = fileSystemRepresentation(pluginPath); char* argv[4]; argv[0] = const_cast<char*>(binaryPath.data()); argv[1] = const_cast<char*>("-scanPlugin"); argv[2] = const_cast<char*>(pluginPathCString.data()); - argv[3] = 0; - - int status; - GUniqueOutPtr<char> stdOut; + argv[3] = nullptr; // 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 @@ -90,27 +119,42 @@ bool PluginProcessProxy::scanPlugin(const String& pluginPath, RawPluginMetaData& } #endif - if (!g_spawn_sync(0, argv, 0, G_SPAWN_STDERR_TO_DEV_NULL, 0, 0, &stdOut.outPtr(), 0, &status, 0)) + int status; + GUniqueOutPtr<char> stdOut; + GUniqueOutPtr<GError> error; + if (!g_spawn_sync(nullptr, argv, nullptr, G_SPAWN_STDERR_TO_DEV_NULL, nullptr, nullptr, &stdOut.outPtr(), nullptr, &status, &error.outPtr())) { + WTFLogAlways("Failed to launch %s: %s", argv[0], error->message); return false; + } - if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS || !stdOut) + if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS) { + WTFLogAlways("Error scanning plugin %s, %s returned %d exit status", argv[2], argv[0], status); return false; + } - String stdOutString = String::fromUTF8(stdOut.get()); + if (!stdOut) { + WTFLogAlways("Error scanning plugin %s, %s didn't write any output to stdout", argv[2], argv[0]); + return false; + } Vector<String> lines; - stdOutString.split(UChar('\n'), true, lines); + String::fromUTF8(stdOut.get()).split(UChar('\n'), true, lines); - if (lines.size() < 3) + if (lines.size() < 3) { + WTFLogAlways("Error scanning plugin %s, too few lines of output provided", argv[2]); return false; + } result.name.swap(lines[0]); result.description.swap(lines[1]); result.mimeDescription.swap(lines[2]); +#if PLATFORM(GTK) + result.requiresGtk2 = requiresGtk2; +#endif return !result.mimeDescription.isEmpty(); -#else // PLATFORM(GTK) || PLATFORM(EFL) +#else // PLATFORM(GTK) return false; -#endif // PLATFORM(GTK) || PLATFORM(EFL) +#endif // PLATFORM(GTK) } #endif // PLUGIN_ARCHITECTURE(X11) |