f41fe7502247aabb36872a09c5cf82dbc6e9df59
[framework/web/webkit-efl.git] / Source / WebKit2 / UIProcess / Plugins / PluginProcessProxy.cpp
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 "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>
41
42 #if PLATFORM(MAC)
43 #include "MachPort.h"
44 #endif
45
46 using namespace WebCore;
47
48 namespace WebKit {
49
50 PassRefPtr<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginModuleInfo& pluginInfo)
51 {
52     return adoptRef(new PluginProcessProxy(PluginProcessManager, pluginInfo));
53 }
54
55 PluginProcessProxy::PluginProcessProxy(PluginProcessManager* PluginProcessManager, const PluginModuleInfo& pluginInfo)
56     : m_pluginProcessManager(PluginProcessManager)
57     , m_pluginInfo(pluginInfo)
58     , m_numPendingConnectionRequests(0)
59 #if PLATFORM(MAC)
60     , m_modalWindowIsShowing(false)
61     , m_fullscreenWindowIsShowing(false)
62     , m_preFullscreenAppPresentationOptions(0)
63 #endif
64 {
65     ProcessLauncher::LaunchOptions launchOptions;
66     launchOptions.processType = ProcessLauncher::PluginProcess;
67 #if PLATFORM(MAC)
68     launchOptions.architecture = pluginInfo.pluginArchitecture;
69     launchOptions.executableHeap = PluginProcessProxy::pluginNeedsExecutableHeap(pluginInfo);
70 #endif
71
72 #if ENABLE(TIZEN_PROCESS_PERMISSION_CONTROL)
73     launchOptions.customExecutablePath = pluginInfo.executablePath;
74 #endif
75
76     m_processLauncher = ProcessLauncher::create(this, launchOptions);
77 }
78
79 PluginProcessProxy::~PluginProcessProxy()
80 {
81 }
82
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)
86 {
87     m_pendingConnectionReplies.append(reply);
88
89     if (m_processLauncher->isLaunching()) {
90         m_numPendingConnectionRequests++;
91         return;
92     }
93     
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);
97 }
98
99 void PluginProcessProxy::getSitesWithData(WebPluginSiteDataManager* webPluginSiteDataManager, uint64_t callbackID)
100 {
101     ASSERT(!m_pendingGetSitesReplies.contains(callbackID));
102     m_pendingGetSitesReplies.set(callbackID, webPluginSiteDataManager);
103
104     if (m_processLauncher->isLaunching()) {
105         m_pendingGetSitesRequests.append(callbackID);
106         return;
107     }
108
109     // Ask the plug-in process for the sites with data.
110     m_connection->send(Messages::PluginProcess::GetSitesWithData(callbackID), 0);
111 }
112
113 void PluginProcessProxy::clearSiteData(WebPluginSiteDataManager* webPluginSiteDataManager, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID)
114 {
115     ASSERT(!m_pendingClearSiteDataReplies.contains(callbackID));
116     m_pendingClearSiteDataReplies.set(callbackID, webPluginSiteDataManager);
117
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);
125         return;
126     }
127
128     // Ask the plug-in process to clear the site data.
129     m_connection->send(Messages::PluginProcess::ClearSiteData(sites, flags, maxAgeInSeconds, callbackID), 0);
130 }
131
132 void PluginProcessProxy::terminate()
133 {
134      m_processLauncher->terminateProcess();
135 }
136
137 void PluginProcessProxy::pluginProcessCrashedOrFailedToLaunch()
138 {
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();
142
143 #if PLATFORM(MAC)
144         reply->send(CoreIPC::Attachment(0, MACH_MSG_TYPE_MOVE_SEND));
145 #elif USE(UNIX_DOMAIN_SOCKETS)
146         reply->send(CoreIPC::Attachment());
147 #else
148         notImplemented();
149 #endif
150     }
151
152     while (!m_pendingGetSitesReplies.isEmpty())
153         didGetSitesWithData(Vector<String>(), m_pendingGetSitesReplies.begin()->first);
154
155     while (!m_pendingClearSiteDataReplies.isEmpty())
156         didClearSiteData(m_pendingClearSiteDataReplies.begin()->first);
157
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);
160 }
161
162 void PluginProcessProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
163 {
164     didReceivePluginProcessProxyMessage(connection, messageID, arguments);
165 }
166
167 void PluginProcessProxy::didClose(CoreIPC::Connection*)
168 {
169 #if PLATFORM(MAC)
170     if (m_modalWindowIsShowing)
171         endModal();
172
173     if (m_fullscreenWindowIsShowing)
174         exitFullscreen();
175 #endif
176
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));
180
181     // This will cause us to be deleted.
182     pluginProcessCrashedOrFailedToLaunch();
183 }
184
185 void PluginProcessProxy::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID)
186 {
187 }
188
189 void PluginProcessProxy::syncMessageSendTimedOut(CoreIPC::Connection*)
190 {
191 }
192
193 void PluginProcessProxy::didFinishLaunching(ProcessLauncher*, CoreIPC::Connection::Identifier connectionIdentifier)
194 {
195     ASSERT(!m_connection);
196
197     if (!connectionIdentifier) {
198         pluginProcessCrashedOrFailedToLaunch();
199         return;
200     }
201     
202     m_connection = CoreIPC::Connection::createServerConnection(connectionIdentifier, this, RunLoop::main());
203 #if PLATFORM(MAC)
204     m_connection->setShouldCloseConnectionOnMachExceptions();
205 #endif
206
207     m_connection->open();
208     
209     PluginProcessCreationParameters parameters;
210
211     parameters.pluginPath = m_pluginInfo.path;
212
213     platformInitializePluginProcess(parameters);
214
215     // Initialize the plug-in host process.
216     m_connection->send(Messages::PluginProcess::InitializePluginProcess(parameters), 0);
217
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();
222
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);
226     }
227     m_pendingClearSiteDataRequests.clear();
228
229     for (unsigned i = 0; i < m_numPendingConnectionRequests; ++i)
230         m_connection->send(Messages::PluginProcess::CreateWebProcessConnection(), 0);
231     
232     m_numPendingConnectionRequests = 0;
233 }
234
235 void PluginProcessProxy::didCreateWebProcessConnection(const CoreIPC::Attachment& connectionIdentifier)
236 {
237     ASSERT(!m_pendingConnectionReplies.isEmpty());
238
239     // Grab the first pending connection reply.
240     RefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply> reply = m_pendingConnectionReplies.takeFirst();
241 #if PLATFORM(MAC)
242     reply->send(CoreIPC::Attachment(connectionIdentifier.port(), MACH_MSG_TYPE_MOVE_SEND));
243 #elif USE(UNIX_DOMAIN_SOCKETS)
244     reply->send(connectionIdentifier);
245 #else
246     notImplemented();
247 #endif
248 }
249
250 void PluginProcessProxy::didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID)
251 {
252     RefPtr<WebPluginSiteDataManager> webPluginSiteDataManager = m_pendingGetSitesReplies.take(callbackID);
253     ASSERT(webPluginSiteDataManager);
254
255     webPluginSiteDataManager->didGetSitesWithDataForSinglePlugin(sites, callbackID);
256 }
257
258 void PluginProcessProxy::didClearSiteData(uint64_t callbackID)
259 {
260     RefPtr<WebPluginSiteDataManager> webPluginSiteDataManager = m_pendingClearSiteDataReplies.take(callbackID);
261     ASSERT(webPluginSiteDataManager);
262     
263     webPluginSiteDataManager->didClearSiteDataForSinglePlugin(callbackID);
264 }
265
266 } // namespace WebKit
267
268 #endif // ENABLE(PLUGIN_PROCESS)