390ee651f63151a5f4ad5b5c58c6335c97b5d1ca
[framework/web/webkit-efl.git] / Source / WebKit2 / UIProcess / Launcher / efl / ProcessLauncherEfl.cpp
1 /*
2     Copyright (C) 2012 Samsung Electronics
3
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Library General Public
6     License as published by the Free Software Foundation; either
7     version 2 of the License, or (at your option) any later version.
8
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Library General Public License for more details.
13
14     You should have received a copy of the GNU Library General Public License
15     along with this library; see the file COPYING.LIB.  If not, write to
16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "ProcessLauncher.h"
22
23 #include "Connection.h"
24 #include "ProcessExecutablePath.h"
25 #include <WebCore/FileSystem.h>
26 #include <WebCore/ResourceHandle.h>
27 #include <WebCore/RunLoop.h>
28 #include <wtf/text/CString.h>
29 #include <wtf/text/WTFString.h>
30
31 #if ENABLE(TIZEN_WRT_LAUNCHING_PERFORMANCE)
32 #include "WebProcessMainEfl.h"
33
34 extern int _ewkArgc;
35 extern char** _ewkArgv;
36 #endif
37
38 using namespace WebCore;
39
40 namespace WebKit {
41
42 #if ENABLE(TIZEN_WRT_LAUNCHING_PERFORMANCE)
43
44 enum {
45     PROCESS_TYPE_NONE,
46     PARENT_PROCESS,
47     CHILD_PROCESS,
48 };
49
50 class StatusForWRTLaunchingPerformance {
51 public:
52     StatusForWRTLaunchingPerformance();
53     void setSkipExec(bool skipExec) { m_skipExec = skipExec; }
54     bool isInitialFork() { return m_isInitialFork; }
55     void setInitialForkAsFalse() { m_isInitialFork = false; }
56     bool skipExec() { return m_skipExec; }
57     bool isParentProcess() { return m_processType == PARENT_PROCESS; }
58     bool isChildProcess() { return m_processType == CHILD_PROCESS; }
59     pid_t pid() { return m_pid; }
60     void forkProcess();
61     void callWebProcessMain();
62     int socket(int index) { return m_sockets[index]; }
63
64 private:
65     bool m_isInitialFork;
66     bool m_skipExec;
67     int m_processType;
68     char* m_argv[3];
69     pid_t m_pid;
70     int m_sockets[2];
71 };
72
73 StatusForWRTLaunchingPerformance::StatusForWRTLaunchingPerformance()
74     : m_isInitialFork(true)
75     , m_skipExec(false)
76     , m_processType(PROCESS_TYPE_NONE)
77     , m_pid(0)
78 {
79     m_argv[0] = m_argv[1] = m_argv[2] = 0;
80     m_sockets[0] = m_sockets[1] = -1;
81 }
82
83 void StatusForWRTLaunchingPerformance::forkProcess()
84 {
85     if (!m_isInitialFork || !m_skipExec) {
86         m_processType = PARENT_PROCESS;
87         return;
88     }
89
90     if (socketpair(AF_UNIX, SOCK_STREAM, 0, m_sockets) < 0) {
91         ASSERT_NOT_REACHED();
92         return;
93     }
94
95     m_pid = fork();
96     if (!m_pid) { // child process
97         close(m_sockets[1]);
98         m_processType = CHILD_PROCESS;
99     }
100     else if (m_pid > 0) {
101         close(m_sockets[0]);
102         m_processType = PARENT_PROCESS;
103     }
104     else {
105         ASSERT_NOT_REACHED();
106         return;
107     }
108 }
109
110 void StatusForWRTLaunchingPerformance::callWebProcessMain()
111 {
112     if (m_processType == CHILD_PROCESS) {
113         String socket = String::format("%d", m_sockets[0]);
114         String executablePath = "/usr/bin/WebProcess";
115         m_argv[0] = strdup(executablePath.utf8().data());
116         if (_ewkArgc > 0 && _ewkArgv && _ewkArgv[0]) {
117             int maxLen = strlen(_ewkArgv[0]);
118             if (maxLen > 0) {
119                 strncpy(_ewkArgv[0], m_argv[0], maxLen);
120                 _ewkArgv[0][maxLen] = 0;
121             }
122         }
123         m_argv[1] = strdup(socket.utf8().data());
124         WebProcessMainEfl(2, m_argv);
125     }
126 }
127
128 static StatusForWRTLaunchingPerformance& getStatus()
129 {
130     static StatusForWRTLaunchingPerformance status;
131     return status;
132 }
133
134 void ProcessLauncher::setSkipExec(bool skipExec)
135 {
136     getStatus().setSkipExec(skipExec);
137 }
138
139 bool ProcessLauncher::isInitialFork()
140 {
141     return getStatus().isInitialFork();
142 }
143
144 bool ProcessLauncher::isParentProcess()
145 {
146     return getStatus().isParentProcess();
147 }
148
149 bool ProcessLauncher::isChildProcess()
150 {
151     return getStatus().isChildProcess();
152 }
153
154 void ProcessLauncher::forkProcess()
155 {
156     getStatus().forkProcess();
157 }
158
159 void ProcessLauncher::callWebProcessMain()
160 {
161     getStatus().callWebProcessMain();
162 }
163 #endif
164
165 void ProcessLauncher::launchProcess()
166 {
167 #if ENABLE(TIZEN_WRT_LAUNCHING_PERFORMANCE)
168     if (getStatus().isInitialFork() && getStatus().skipExec()) {
169         getStatus().setInitialForkAsFalse();
170         if (getStatus().isParentProcess()) { // parent process;
171             m_processIdentifier = getStatus().pid();
172             // We've finished launching the process, message back to the main run loop.
173             RunLoop::main()->dispatch(bind(&ProcessLauncher::didFinishLaunchingProcess, this, getStatus().pid() , getStatus().socket(1)));
174         }
175         return;
176     }
177 #endif
178
179     int sockets[2];
180     if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) {
181         ASSERT_NOT_REACHED();
182         return;
183     }
184
185     pid_t pid = fork();
186 #if ENABLE(TIZEN_WRT_LAUNCHING_PERFORMANCE)
187     getStatus().setInitialForkAsFalse();
188 #endif
189     if (!pid) { // child process
190         close(sockets[1]);
191 #if ENABLE(TIZEN_WEBKIT2_GIVE_SEPARATE_PROCESS_GROUP_ID_TO_WEBPROCESS)
192         setsid();
193 #endif
194         String socket = String::format("%d", sockets[0]);
195         String executablePath;
196         switch (m_launchOptions.processType) {
197         case WebProcess:
198 #if ENABLE(TIZEN_PROCESS_PERMISSION_CONTROL)
199             if (!m_launchOptions.customExecutablePath.isEmpty()) {
200                 executablePath = m_launchOptions.customExecutablePath;
201                 TIZEN_LOGI("web process executable path: %s", executablePath.utf8().data());
202             } else
203 #endif
204                 executablePath = executablePathOfWebProcess();
205             break;
206         case PluginProcess:
207 #if ENABLE(TIZEN_PROCESS_PERMISSION_CONTROL)
208             {
209                 // this env is used for tizen wrt process pool, and has highest priority for use.
210                 const char* pathForProcessPool = getenv("PLUGIN_PROCESS_EXECUTABLE_PATH_FOR_PROCESS_POOL");
211                 if (pathForProcessPool) {
212                     executablePath = String::fromUTF8(pathForProcessPool);
213                     TIZEN_LOGI("plugin process executable path: %s", executablePath.utf8().data());
214                     break;
215                 }
216             }
217
218             if (!m_launchOptions.customExecutablePath.isEmpty()) {
219                 executablePath = m_launchOptions.customExecutablePath;
220                 TIZEN_LOGI("plugin process executable path: %s", executablePath.utf8().data());
221             } else
222 #endif
223                 executablePath = executablePathOfPluginProcess();
224             break;
225         default:
226             ASSERT_NOT_REACHED();
227             return;
228         }
229
230 #ifndef NDEBUG
231         if (m_launchOptions.processCmdPrefix.isEmpty())
232 #endif
233             execl(executablePath.utf8().data(), executablePath.utf8().data(), socket.utf8().data(), static_cast<char*>(0));
234 #ifndef NDEBUG
235         else {
236             String cmd = makeString(m_launchOptions.processCmdPrefix, ' ', executablePath, ' ', socket);
237             if (system(cmd.utf8().data()) == -1) {
238                 ASSERT_NOT_REACHED();
239                 return;
240             }
241         }
242 #endif
243     } else if (pid > 0) { // parent process;
244         close(sockets[0]);
245         m_processIdentifier = pid;
246         // We've finished launching the process, message back to the main run loop.
247         RunLoop::main()->dispatch(bind(&ProcessLauncher::didFinishLaunchingProcess, this, pid, sockets[1]));
248     } else {
249         ASSERT_NOT_REACHED();
250         return;
251     }
252 }
253
254 void ProcessLauncher::terminateProcess()
255 {
256     if (!m_processIdentifier)
257         return;
258     kill(m_processIdentifier, SIGKILL);
259 }
260
261 void ProcessLauncher::platformInvalidate()
262 {
263 }
264
265 } // namespace WebKit