• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 "PluginProcessProxy.h"
28 
29 #if ENABLE(PLUGIN_PROCESS)
30 
31 #include "PluginProcessCreationParameters.h"
32 #include "PluginProcessManager.h"
33 #include "PluginProcessMessages.h"
34 #include "RunLoop.h"
35 #include "WebCoreArgumentCoders.h"
36 #include "WebPluginSiteDataManager.h"
37 #include "WebProcessProxy.h"
38 
39 #if PLATFORM(MAC)
40 #include "MachPort.h"
41 #endif
42 
43 namespace WebKit {
44 
create(PluginProcessManager * PluginProcessManager,const PluginInfoStore::Plugin & pluginInfo)45 PassOwnPtr<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginInfoStore::Plugin& pluginInfo)
46 {
47     return adoptPtr(new PluginProcessProxy(PluginProcessManager, pluginInfo));
48 }
49 
PluginProcessProxy(PluginProcessManager * PluginProcessManager,const PluginInfoStore::Plugin & pluginInfo)50 PluginProcessProxy::PluginProcessProxy(PluginProcessManager* PluginProcessManager, const PluginInfoStore::Plugin& pluginInfo)
51     : m_pluginProcessManager(PluginProcessManager)
52     , m_pluginInfo(pluginInfo)
53     , m_numPendingConnectionRequests(0)
54 #if PLATFORM(MAC)
55     , m_modalWindowIsShowing(false)
56     , m_fullscreenWindowIsShowing(false)
57     , m_preFullscreenAppPresentationOptions(0)
58 #endif
59 {
60     ProcessLauncher::LaunchOptions launchOptions;
61     launchOptions.processType = ProcessLauncher::PluginProcess;
62 #if PLATFORM(MAC)
63     launchOptions.architecture = pluginInfo.pluginArchitecture;
64     launchOptions.executableHeap = PluginProcessProxy::pluginNeedsExecutableHeap(pluginInfo);
65 #endif
66 
67     m_processLauncher = ProcessLauncher::create(this, launchOptions);
68 }
69 
~PluginProcessProxy()70 PluginProcessProxy::~PluginProcessProxy()
71 {
72 }
73 
74 // Asks the plug-in process to create a new connection to a web process. The connection identifier will be
75 // encoded in the given argument encoder and sent back to the connection of the given web process.
getPluginProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply)76 void PluginProcessProxy::getPluginProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply)
77 {
78     m_pendingConnectionReplies.append(reply);
79 
80     if (m_processLauncher->isLaunching()) {
81         m_numPendingConnectionRequests++;
82         return;
83     }
84 
85     // Ask the plug-in process to create a connection. Since the plug-in can be waiting for a synchronous reply
86     // we need to make sure that this message is always processed, even when the plug-in is waiting for a synchronus reply.
87     m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0, CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply);
88 }
89 
getSitesWithData(WebPluginSiteDataManager * webPluginSiteDataManager,uint64_t callbackID)90 void PluginProcessProxy::getSitesWithData(WebPluginSiteDataManager* webPluginSiteDataManager, uint64_t callbackID)
91 {
92     ASSERT(!m_pendingGetSitesReplies.contains(callbackID));
93     m_pendingGetSitesReplies.set(callbackID, webPluginSiteDataManager);
94 
95     if (m_processLauncher->isLaunching()) {
96         m_pendingGetSitesRequests.append(callbackID);
97         return;
98     }
99 
100     // Ask the plug-in process for the sites with data.
101     m_connection->send(Messages::PluginProcess::GetSitesWithData(callbackID), 0);
102 }
103 
clearSiteData(WebPluginSiteDataManager * webPluginSiteDataManager,const Vector<String> & sites,uint64_t flags,uint64_t maxAgeInSeconds,uint64_t callbackID)104 void PluginProcessProxy::clearSiteData(WebPluginSiteDataManager* webPluginSiteDataManager, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID)
105 {
106     ASSERT(!m_pendingClearSiteDataReplies.contains(callbackID));
107     m_pendingClearSiteDataReplies.set(callbackID, webPluginSiteDataManager);
108 
109     if (m_processLauncher->isLaunching()) {
110         ClearSiteDataRequest request;
111         request.sites = sites;
112         request.flags = flags;
113         request.maxAgeInSeconds = maxAgeInSeconds;
114         request.callbackID = callbackID;
115         m_pendingClearSiteDataRequests.append(request);
116         return;
117     }
118 
119     // Ask the plug-in process to clear the site data.
120     m_connection->send(Messages::PluginProcess::ClearSiteData(sites, flags, maxAgeInSeconds, callbackID), 0);
121 }
122 
terminate()123 void PluginProcessProxy::terminate()
124 {
125      m_processLauncher->terminateProcess();
126 }
127 
pluginProcessCrashedOrFailedToLaunch()128 void PluginProcessProxy::pluginProcessCrashedOrFailedToLaunch()
129 {
130     // The plug-in process must have crashed or exited, send any pending sync replies we might have.
131     while (!m_pendingConnectionReplies.isEmpty()) {
132         RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply = m_pendingConnectionReplies.takeFirst();
133 
134 #if PLATFORM(MAC)
135         reply->send(CoreIPC::MachPort(0, MACH_MSG_TYPE_MOVE_SEND));
136 #else
137         // FIXME: Implement.
138         ASSERT_NOT_REACHED();
139 #endif
140     }
141 
142     while (!m_pendingGetSitesReplies.isEmpty())
143         didGetSitesWithData(Vector<String>(), m_pendingGetSitesReplies.begin()->first);
144 
145     while (!m_pendingClearSiteDataReplies.isEmpty())
146         didClearSiteData(m_pendingClearSiteDataReplies.begin()->first);
147 
148     // Tell the plug-in process manager to forget about this plug-in process proxy.
149     m_pluginProcessManager->removePluginProcessProxy(this);
150     delete this;
151 }
152 
didReceiveMessage(CoreIPC::Connection * connection,CoreIPC::MessageID messageID,CoreIPC::ArgumentDecoder * arguments)153 void PluginProcessProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
154 {
155     didReceivePluginProcessProxyMessage(connection, messageID, arguments);
156 }
157 
didClose(CoreIPC::Connection *)158 void PluginProcessProxy::didClose(CoreIPC::Connection*)
159 {
160 #if PLATFORM(MAC)
161     if (m_modalWindowIsShowing)
162         endModal();
163 
164     if (m_fullscreenWindowIsShowing)
165         exitFullscreen();
166 #endif
167 
168     pluginProcessCrashedOrFailedToLaunch();
169 }
170 
didReceiveInvalidMessage(CoreIPC::Connection *,CoreIPC::MessageID)171 void PluginProcessProxy::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID)
172 {
173 }
174 
syncMessageSendTimedOut(CoreIPC::Connection *)175 void PluginProcessProxy::syncMessageSendTimedOut(CoreIPC::Connection*)
176 {
177 }
178 
didFinishLaunching(ProcessLauncher *,CoreIPC::Connection::Identifier connectionIdentifier)179 void PluginProcessProxy::didFinishLaunching(ProcessLauncher*, CoreIPC::Connection::Identifier connectionIdentifier)
180 {
181     ASSERT(!m_connection);
182 
183     if (!connectionIdentifier) {
184         pluginProcessCrashedOrFailedToLaunch();
185         return;
186     }
187 
188     m_connection = CoreIPC::Connection::createServerConnection(connectionIdentifier, this, RunLoop::main());
189     m_connection->open();
190 
191     PluginProcessCreationParameters parameters;
192 
193     parameters.pluginPath = m_pluginInfo.path;
194 
195     platformInitializePluginProcess(parameters);
196 
197     // Initialize the plug-in host process.
198     m_connection->send(Messages::PluginProcess::InitializePluginProcess(parameters), 0);
199 
200     // Send all our pending requests.
201     for (size_t i = 0; i < m_pendingGetSitesRequests.size(); ++i)
202         m_connection->send(Messages::PluginProcess::GetSitesWithData(m_pendingGetSitesRequests[i]), 0);
203     m_pendingGetSitesRequests.clear();
204 
205     for (size_t i = 0; i < m_pendingClearSiteDataRequests.size(); ++i) {
206         const ClearSiteDataRequest& request = m_pendingClearSiteDataRequests[i];
207         m_connection->send(Messages::PluginProcess::ClearSiteData(request.sites, request.flags, request.maxAgeInSeconds, request.callbackID), 0);
208     }
209     m_pendingClearSiteDataRequests.clear();
210 
211     for (unsigned i = 0; i < m_numPendingConnectionRequests; ++i)
212         m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0);
213 
214     m_numPendingConnectionRequests = 0;
215 }
216 
217 #if PLATFORM(MAC)
didCreateWebProcessConnection(const CoreIPC::MachPort & machPort)218 void PluginProcessProxy::didCreateWebProcessConnection(const CoreIPC::MachPort& machPort)
219 {
220     ASSERT(!m_pendingConnectionReplies.isEmpty());
221 
222     // Grab the first pending connection reply.
223     RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply = m_pendingConnectionReplies.takeFirst();
224 
225     reply->send(CoreIPC::MachPort(machPort.port(), MACH_MSG_TYPE_MOVE_SEND));
226 }
227 #endif
228 
didGetSitesWithData(const Vector<String> & sites,uint64_t callbackID)229 void PluginProcessProxy::didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID)
230 {
231     RefPtr<WebPluginSiteDataManager> webPluginSiteDataManager = m_pendingGetSitesReplies.take(callbackID);
232     ASSERT(webPluginSiteDataManager);
233 
234     webPluginSiteDataManager->didGetSitesWithDataForSinglePlugin(sites, callbackID);
235 }
236 
didClearSiteData(uint64_t callbackID)237 void PluginProcessProxy::didClearSiteData(uint64_t callbackID)
238 {
239     RefPtr<WebPluginSiteDataManager> webPluginSiteDataManager = m_pendingClearSiteDataReplies.take(callbackID);
240     ASSERT(webPluginSiteDataManager);
241 
242     webPluginSiteDataManager->didClearSiteDataForSinglePlugin(callbackID);
243 }
244 
245 } // namespace WebKit
246 
247 #endif // ENABLE(PLUGIN_PROCESS)
248