2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "PluginProcessProxy.h"
29 #if ENABLE(PLUGIN_PROCESS)
31 #include "PluginProcessCreationParameters.h"
32 #include "PluginProcessManager.h"
33 #include "PluginProcessMessages.h"
34 #include "WebContext.h"
35 #include "WebCoreArgumentCoders.h"
36 #include "WebPluginSiteDataManager.h"
37 #include "WebProcessMessages.h"
38 #include "WebProcessProxy.h"
39 #include <WebCore/NotImplemented.h>
40 #include <WebCore/RunLoop.h>
46 using namespace WebCore;
50 PassRefPtr<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginModuleInfo& pluginInfo)
52 return adoptRef(new PluginProcessProxy(PluginProcessManager, pluginInfo));
55 PluginProcessProxy::PluginProcessProxy(PluginProcessManager* PluginProcessManager, const PluginModuleInfo& pluginInfo)
56 : m_pluginProcessManager(PluginProcessManager)
57 , m_pluginInfo(pluginInfo)
58 , m_numPendingConnectionRequests(0)
60 , m_modalWindowIsShowing(false)
61 , m_fullscreenWindowIsShowing(false)
62 , m_preFullscreenAppPresentationOptions(0)
65 ProcessLauncher::LaunchOptions launchOptions;
66 launchOptions.processType = ProcessLauncher::PluginProcess;
68 launchOptions.architecture = pluginInfo.pluginArchitecture;
69 launchOptions.executableHeap = PluginProcessProxy::pluginNeedsExecutableHeap(pluginInfo);
72 #if ENABLE(TIZEN_PROCESS_PERMISSION_CONTROL)
73 launchOptions.customExecutablePath = pluginInfo.executablePath;
76 m_processLauncher = ProcessLauncher::create(this, launchOptions);
79 PluginProcessProxy::~PluginProcessProxy()
83 // Asks the plug-in process to create a new connection to a web process. The connection identifier will be
84 // encoded in the given argument encoder and sent back to the connection of the given web process.
85 void PluginProcessProxy::getPluginProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply)
87 m_pendingConnectionReplies.append(reply);
89 if (m_processLauncher->isLaunching()) {
90 m_numPendingConnectionRequests++;
94 // Ask the plug-in process to create a connection. Since the plug-in can be waiting for a synchronous reply
95 // we need to make sure that this message is always processed, even when the plug-in is waiting for a synchronus reply.
96 m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0, CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply);
99 void PluginProcessProxy::getSitesWithData(WebPluginSiteDataManager* webPluginSiteDataManager, uint64_t callbackID)
101 ASSERT(!m_pendingGetSitesReplies.contains(callbackID));
102 m_pendingGetSitesReplies.set(callbackID, webPluginSiteDataManager);
104 if (m_processLauncher->isLaunching()) {
105 m_pendingGetSitesRequests.append(callbackID);
109 // Ask the plug-in process for the sites with data.
110 m_connection->send(Messages::PluginProcess::GetSitesWithData(callbackID), 0);
113 void PluginProcessProxy::clearSiteData(WebPluginSiteDataManager* webPluginSiteDataManager, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID)
115 ASSERT(!m_pendingClearSiteDataReplies.contains(callbackID));
116 m_pendingClearSiteDataReplies.set(callbackID, webPluginSiteDataManager);
118 if (m_processLauncher->isLaunching()) {
119 ClearSiteDataRequest request;
120 request.sites = sites;
121 request.flags = flags;
122 request.maxAgeInSeconds = maxAgeInSeconds;
123 request.callbackID = callbackID;
124 m_pendingClearSiteDataRequests.append(request);
128 // Ask the plug-in process to clear the site data.
129 m_connection->send(Messages::PluginProcess::ClearSiteData(sites, flags, maxAgeInSeconds, callbackID), 0);
132 void PluginProcessProxy::terminate()
134 m_processLauncher->terminateProcess();
137 void PluginProcessProxy::pluginProcessCrashedOrFailedToLaunch()
139 // The plug-in process must have crashed or exited, send any pending sync replies we might have.
140 while (!m_pendingConnectionReplies.isEmpty()) {
141 RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply = m_pendingConnectionReplies.takeFirst();
144 reply->send(CoreIPC::Attachment(0, MACH_MSG_TYPE_MOVE_SEND));
145 #elif USE(UNIX_DOMAIN_SOCKETS)
146 reply->send(CoreIPC::Attachment());
152 while (!m_pendingGetSitesReplies.isEmpty())
153 didGetSitesWithData(Vector<String>(), m_pendingGetSitesReplies.begin()->first);
155 while (!m_pendingClearSiteDataReplies.isEmpty())
156 didClearSiteData(m_pendingClearSiteDataReplies.begin()->first);
158 // Tell the plug-in process manager to forget about this plug-in process proxy. This may cause us to be deleted.
159 m_pluginProcessManager->removePluginProcessProxy(this);
162 void PluginProcessProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
164 didReceivePluginProcessProxyMessage(connection, messageID, arguments);
167 void PluginProcessProxy::didClose(CoreIPC::Connection*)
170 if (m_modalWindowIsShowing)
173 if (m_fullscreenWindowIsShowing)
177 const Vector<WebContext*>& contexts = WebContext::allContexts();
178 for (size_t i = 0; i < contexts.size(); ++i)
179 contexts[i]->sendToAllProcesses(Messages::WebProcess::PluginProcessCrashed(m_pluginInfo.path));
181 // This will cause us to be deleted.
182 pluginProcessCrashedOrFailedToLaunch();
185 void PluginProcessProxy::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID)
189 void PluginProcessProxy::syncMessageSendTimedOut(CoreIPC::Connection*)
193 void PluginProcessProxy::didFinishLaunching(ProcessLauncher*, CoreIPC::Connection::Identifier connectionIdentifier)
195 ASSERT(!m_connection);
197 if (!connectionIdentifier) {
198 pluginProcessCrashedOrFailedToLaunch();
202 m_connection = CoreIPC::Connection::createServerConnection(connectionIdentifier, this, RunLoop::main());
204 m_connection->setShouldCloseConnectionOnMachExceptions();
207 m_connection->open();
209 PluginProcessCreationParameters parameters;
211 parameters.pluginPath = m_pluginInfo.path;
213 platformInitializePluginProcess(parameters);
215 // Initialize the plug-in host process.
216 m_connection->send(Messages::PluginProcess::InitializePluginProcess(parameters), 0);
218 // Send all our pending requests.
219 for (size_t i = 0; i < m_pendingGetSitesRequests.size(); ++i)
220 m_connection->send(Messages::PluginProcess::GetSitesWithData(m_pendingGetSitesRequests[i]), 0);
221 m_pendingGetSitesRequests.clear();
223 for (size_t i = 0; i < m_pendingClearSiteDataRequests.size(); ++i) {
224 const ClearSiteDataRequest& request = m_pendingClearSiteDataRequests[i];
225 m_connection->send(Messages::PluginProcess::ClearSiteData(request.sites, request.flags, request.maxAgeInSeconds, request.callbackID), 0);
227 m_pendingClearSiteDataRequests.clear();
229 for (unsigned i = 0; i < m_numPendingConnectionRequests; ++i)
230 m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0);
232 m_numPendingConnectionRequests = 0;
235 void PluginProcessProxy::didCreateWebProcessConnection(const CoreIPC::Attachment& connectionIdentifier)
237 ASSERT(!m_pendingConnectionReplies.isEmpty());
239 // Grab the first pending connection reply.
240 RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply = m_pendingConnectionReplies.takeFirst();
242 reply->send(CoreIPC::Attachment(connectionIdentifier.port(), MACH_MSG_TYPE_MOVE_SEND));
243 #elif USE(UNIX_DOMAIN_SOCKETS)
244 reply->send(connectionIdentifier);
250 void PluginProcessProxy::didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID)
252 RefPtr<WebPluginSiteDataManager> webPluginSiteDataManager = m_pendingGetSitesReplies.take(callbackID);
253 ASSERT(webPluginSiteDataManager);
255 webPluginSiteDataManager->didGetSitesWithDataForSinglePlugin(sites, callbackID);
258 void PluginProcessProxy::didClearSiteData(uint64_t callbackID)
260 RefPtr<WebPluginSiteDataManager> webPluginSiteDataManager = m_pendingClearSiteDataReplies.take(callbackID);
261 ASSERT(webPluginSiteDataManager);
263 webPluginSiteDataManager->didClearSiteDataForSinglePlugin(callbackID);
266 } // namespace WebKit
268 #endif // ENABLE(PLUGIN_PROCESS)