1/*
2 * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "PluginProcessManager.h"
28
29#if ENABLE(NETSCAPE_PLUGIN_API)
30
31#include "PluginProcessProxy.h"
32#include "WebsiteDataFetchOption.h"
33#include <wtf/CryptographicallyRandomNumber.h>
34#include <wtf/NeverDestroyed.h>
35#include <wtf/StdLibExtras.h>
36#include <wtf/text/WTFString.h>
37
38namespace WebKit {
39
40PluginProcessManager& PluginProcessManager::singleton()
41{
42 static NeverDestroyed<PluginProcessManager> pluginProcessManager;
43 return pluginProcessManager;
44}
45
46PluginProcessManager::PluginProcessManager()
47#if PLATFORM(COCOA)
48 : m_processSuppressionDisabledForPageCounter([this](RefCounterEvent event) { updateProcessSuppressionDisabled(event); })
49#endif
50{
51}
52
53uint64_t PluginProcessManager::pluginProcessToken(const PluginModuleInfo& pluginModuleInfo, PluginProcessType pluginProcessType, PluginProcessSandboxPolicy pluginProcessSandboxPolicy)
54{
55 // See if we know this token already.
56 for (size_t i = 0; i < m_pluginProcessTokens.size(); ++i) {
57 const PluginProcessAttributes& attributes = m_pluginProcessTokens[i].first;
58
59 if (attributes.moduleInfo.path == pluginModuleInfo.path
60 && attributes.processType == pluginProcessType
61 && attributes.sandboxPolicy == pluginProcessSandboxPolicy)
62 return m_pluginProcessTokens[i].second;
63 }
64
65 uint64_t token;
66 while (true) {
67 cryptographicallyRandomValues(&token, sizeof(token));
68
69 if (m_knownTokens.isValidValue(token) && !m_knownTokens.contains(token))
70 break;
71 }
72
73 PluginProcessAttributes attributes;
74 attributes.moduleInfo = pluginModuleInfo;
75 attributes.processType = pluginProcessType;
76 attributes.sandboxPolicy = pluginProcessSandboxPolicy;
77
78 m_pluginProcessTokens.append(std::make_pair(WTFMove(attributes), token));
79 m_knownTokens.add(token);
80
81 return token;
82}
83
84void PluginProcessManager::getPluginProcessConnection(uint64_t pluginProcessToken, Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply&& reply)
85{
86 ASSERT(pluginProcessToken);
87
88 PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(pluginProcessToken);
89 pluginProcess->getPluginProcessConnection(WTFMove(reply));
90}
91
92void PluginProcessManager::removePluginProcessProxy(PluginProcessProxy* pluginProcessProxy)
93{
94 size_t vectorIndex = m_pluginProcesses.find(pluginProcessProxy);
95 ASSERT(vectorIndex != notFound);
96
97 m_pluginProcesses.remove(vectorIndex);
98}
99
100void PluginProcessManager::fetchWebsiteData(const PluginModuleInfo& plugin, OptionSet<WebsiteDataFetchOption> fetchOptions, WTF::Function<void (Vector<String>)>&& completionHandler)
101{
102 auto token = pluginProcessToken(plugin, PluginProcessTypeNormal, PluginProcessSandboxPolicyNormal);
103 auto pluginProcess = fetchOptions.contains(WebsiteDataFetchOption::DoNotCreateProcesses) ? getPluginProcess(token) : getOrCreatePluginProcess(token);
104 if (!pluginProcess) {
105 completionHandler({ });
106 return;
107 }
108
109 pluginProcess->fetchWebsiteData(WTFMove(completionHandler));
110}
111
112void PluginProcessManager::deleteWebsiteData(const PluginModuleInfo& plugin, WallTime modifiedSince, WTF::Function<void ()>&& completionHandler)
113{
114 PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(pluginProcessToken(plugin, PluginProcessTypeNormal, PluginProcessSandboxPolicyNormal));
115 pluginProcess->deleteWebsiteData(modifiedSince, WTFMove(completionHandler));
116}
117
118void PluginProcessManager::deleteWebsiteDataForHostNames(const PluginModuleInfo& plugin, const Vector<String>& hostNames,WTF::Function<void ()>&& completionHandler)
119{
120 PluginProcessProxy* pluginProcess = getOrCreatePluginProcess(pluginProcessToken(plugin, PluginProcessTypeNormal, PluginProcessSandboxPolicyNormal));
121 pluginProcess->deleteWebsiteDataForHostNames(hostNames, WTFMove(completionHandler));
122}
123
124PluginProcessProxy* PluginProcessManager::getPluginProcess(uint64_t pluginProcessToken)
125{
126 for (const auto& pluginProcess : m_pluginProcesses) {
127 if (pluginProcess->pluginProcessToken() == pluginProcessToken)
128 return pluginProcess.get();
129 }
130
131 return nullptr;
132}
133
134#if OS(LINUX)
135void PluginProcessManager::sendMemoryPressureEvent(bool isCritical)
136{
137 for (auto& pluginProcess : m_pluginProcesses)
138 pluginProcess->sendMemoryPressureEvent(isCritical);
139}
140#endif
141
142PluginProcessProxy* PluginProcessManager::getOrCreatePluginProcess(uint64_t pluginProcessToken)
143{
144 if (auto existingProcess = getPluginProcess(pluginProcessToken))
145 return existingProcess;
146
147 for (auto& attributesAndToken : m_pluginProcessTokens) {
148 if (attributesAndToken.second == pluginProcessToken) {
149 auto pluginProcess = PluginProcessProxy::create(this, attributesAndToken.first, attributesAndToken.second);
150 PluginProcessProxy* pluginProcessPtr = pluginProcess.ptr();
151 m_pluginProcesses.append(WTFMove(pluginProcess));
152 return pluginProcessPtr;
153 }
154 }
155
156 return nullptr;
157}
158
159} // namespace WebKit
160
161#endif // ENABLE(NETSCAPE_PLUGIN_API)
162