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"
35 #include "WebContext.h"
36 #include "WebCoreArgumentCoders.h"
37 #include "WebPluginSiteDataManager.h"
38 #include "WebProcessMessages.h"
39 #include "WebProcessProxy.h"
40 #include <WebCore/NotImplemented.h>
48 PassOwnPtr<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginModuleInfo& pluginInfo)
50 return adoptPtr(new PluginProcessProxy(PluginProcessManager, pluginInfo));
53 PluginProcessProxy::PluginProcessProxy(PluginProcessManager* PluginProcessManager, const PluginModuleInfo& pluginInfo)
54 : m_pluginProcessManager(PluginProcessManager)
55 , m_pluginInfo(pluginInfo)
56 , m_numPendingConnectionRequests(0)
58 , m_modalWindowIsShowing(false)
59 , m_fullscreenWindowIsShowing(false)
60 , m_preFullscreenAppPresentationOptions(0)
63 ProcessLauncher::LaunchOptions launchOptions;
64 launchOptions.processType = ProcessLauncher::PluginProcess;
66 launchOptions.architecture = pluginInfo.pluginArchitecture;
67 launchOptions.executableHeap = PluginProcessProxy::pluginNeedsExecutableHeap(pluginInfo);
70 m_processLauncher = ProcessLauncher::create(this, launchOptions);
73 PluginProcessProxy::~PluginProcessProxy()
77 // Asks the plug-in process to create a new connection to a web process. The connection identifier will be
78 // encoded in the given argument encoder and sent back to the connection of the given web process.
79 void PluginProcessProxy::getPluginProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply)
81 m_pendingConnectionReplies.append(reply);
83 if (m_processLauncher->isLaunching()) {
84 m_numPendingConnectionRequests++;
88 // Ask the plug-in process to create a connection. Since the plug-in can be waiting for a synchronous reply
89 // we need to make sure that this message is always processed, even when the plug-in is waiting for a synchronus reply.
90 m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0, CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply);
93 void PluginProcessProxy::getSitesWithData(WebPluginSiteDataManager* webPluginSiteDataManager, uint64_t callbackID)
95 ASSERT(!m_pendingGetSitesReplies.contains(callbackID));
96 m_pendingGetSitesReplies.set(callbackID, webPluginSiteDataManager);
98 if (m_processLauncher->isLaunching()) {
99 m_pendingGetSitesRequests.append(callbackID);
103 // Ask the plug-in process for the sites with data.
104 m_connection->send(Messages::PluginProcess::GetSitesWithData(callbackID), 0);
107 void PluginProcessProxy::clearSiteData(WebPluginSiteDataManager* webPluginSiteDataManager, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID)
109 ASSERT(!m_pendingClearSiteDataReplies.contains(callbackID));
110 m_pendingClearSiteDataReplies.set(callbackID, webPluginSiteDataManager);
112 if (m_processLauncher->isLaunching()) {
113 ClearSiteDataRequest request;
114 request.sites = sites;
115 request.flags = flags;
116 request.maxAgeInSeconds = maxAgeInSeconds;
117 request.callbackID = callbackID;
118 m_pendingClearSiteDataRequests.append(request);
122 // Ask the plug-in process to clear the site data.
123 m_connection->send(Messages::PluginProcess::ClearSiteData(sites, flags, maxAgeInSeconds, callbackID), 0);
126 void PluginProcessProxy::terminate()
128 m_processLauncher->terminateProcess();
131 void PluginProcessProxy::pluginProcessCrashedOrFailedToLaunch()
133 // The plug-in process must have crashed or exited, send any pending sync replies we might have.
134 while (!m_pendingConnectionReplies.isEmpty()) {
135 RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply = m_pendingConnectionReplies.takeFirst();
138 reply->send(CoreIPC::Attachment(0, MACH_MSG_TYPE_MOVE_SEND));
139 #elif USE(UNIX_DOMAIN_SOCKETS)
140 reply->send(CoreIPC::Attachment());
146 while (!m_pendingGetSitesReplies.isEmpty())
147 didGetSitesWithData(Vector<String>(), m_pendingGetSitesReplies.begin()->first);
149 while (!m_pendingClearSiteDataReplies.isEmpty())
150 didClearSiteData(m_pendingClearSiteDataReplies.begin()->first);
152 // Tell the plug-in process manager to forget about this plug-in process proxy.
153 m_pluginProcessManager->removePluginProcessProxy(this);
157 void PluginProcessProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
159 didReceivePluginProcessProxyMessage(connection, messageID, arguments);
162 void PluginProcessProxy::didClose(CoreIPC::Connection*)
165 if (m_modalWindowIsShowing)
168 if (m_fullscreenWindowIsShowing)
172 const Vector<WebContext*>& contexts = WebContext::allContexts();
173 for (size_t i = 0; i < contexts.size(); ++i)
174 contexts[i]->sendToAllProcesses(Messages::WebProcess::PluginProcessCrashed(m_pluginInfo.path));
176 // This will cause us to be deleted.
177 pluginProcessCrashedOrFailedToLaunch();
180 void PluginProcessProxy::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID)
184 void PluginProcessProxy::syncMessageSendTimedOut(CoreIPC::Connection*)
188 void PluginProcessProxy::didFinishLaunching(ProcessLauncher*, CoreIPC::Connection::Identifier connectionIdentifier)
190 ASSERT(!m_connection);
192 if (!connectionIdentifier) {
193 pluginProcessCrashedOrFailedToLaunch();
197 m_connection = CoreIPC::Connection::createServerConnection(connectionIdentifier, this, RunLoop::main());
199 m_connection->setShouldCloseConnectionOnMachExceptions();
202 m_connection->open();
204 PluginProcessCreationParameters parameters;
206 parameters.pluginPath = m_pluginInfo.path;
208 platformInitializePluginProcess(parameters);
210 // Initialize the plug-in host process.
211 m_connection->send(Messages::PluginProcess::InitializePluginProcess(parameters), 0);
213 // Send all our pending requests.
214 for (size_t i = 0; i < m_pendingGetSitesRequests.size(); ++i)
215 m_connection->send(Messages::PluginProcess::GetSitesWithData(m_pendingGetSitesRequests[i]), 0);
216 m_pendingGetSitesRequests.clear();
218 for (size_t i = 0; i < m_pendingClearSiteDataRequests.size(); ++i) {
219 const ClearSiteDataRequest& request = m_pendingClearSiteDataRequests[i];
220 m_connection->send(Messages::PluginProcess::ClearSiteData(request.sites, request.flags, request.maxAgeInSeconds, request.callbackID), 0);
222 m_pendingClearSiteDataRequests.clear();
224 for (unsigned i = 0; i < m_numPendingConnectionRequests; ++i)
225 m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0);
227 m_numPendingConnectionRequests = 0;
230 void PluginProcessProxy::didCreateWebProcessConnection(const CoreIPC::Attachment& connectionIdentifier)
232 ASSERT(!m_pendingConnectionReplies.isEmpty());
234 // Grab the first pending connection reply.
235 RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply = m_pendingConnectionReplies.takeFirst();
238 reply->send(CoreIPC::Attachment(connectionIdentifier.port(), MACH_MSG_TYPE_MOVE_SEND));
239 #elif USE(UNIX_DOMAIN_SOCKETS)
240 reply->send(connectionIdentifier);
246 void PluginProcessProxy::didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID)
248 RefPtr<WebPluginSiteDataManager> webPluginSiteDataManager = m_pendingGetSitesReplies.take(callbackID);
249 ASSERT(webPluginSiteDataManager);
251 webPluginSiteDataManager->didGetSitesWithDataForSinglePlugin(sites, callbackID);
254 void PluginProcessProxy::didClearSiteData(uint64_t callbackID)
256 RefPtr<WebPluginSiteDataManager> webPluginSiteDataManager = m_pendingClearSiteDataReplies.take(callbackID);
257 ASSERT(webPluginSiteDataManager);
259 webPluginSiteDataManager->didClearSiteDataForSinglePlugin(callbackID);
262 } // namespace WebKit
264 #endif // ENABLE(PLUGIN_PROCESS)