WebProcessMainQt.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * Copyright (C) 2013 University of Szeged
  3. * Copyright (C) 2013 Renata Hodovan <reni@inf.u-szeged.hu>
  4. * Copyright (C) 2010 Apple Inc. All rights reserved.
  5. * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
  17. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  18. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  19. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
  20. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  23. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  24. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  25. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  26. * THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include "config.h"
  29. #include "WebProcess.h"
  30. #include "WebKit2Initialize.h"
  31. #include <QGuiApplication>
  32. #include <QList>
  33. #include <QNetworkProxyFactory>
  34. #include <QString>
  35. #include <QStringList>
  36. #include <QUrl>
  37. #include <WebCore/RunLoop.h>
  38. #include <errno.h>
  39. #ifndef NDEBUG
  40. #if !OS(WINDOWS)
  41. #include <unistd.h>
  42. #endif
  43. #endif
  44. #ifndef NDEBUG
  45. #include <QDebug>
  46. #endif
  47. #if OS(DARWIN) && !USE(UNIX_DOMAIN_SOCKETS)
  48. #include <servers/bootstrap.h>
  49. extern "C" kern_return_t bootstrap_look_up2(mach_port_t, const name_t, mach_port_t*, pid_t, uint64_t);
  50. #endif
  51. #if ENABLE(SUID_SANDBOX_LINUX)
  52. #include "SandboxEnvironmentLinux.h"
  53. #include <sys/wait.h>
  54. #endif
  55. using namespace WebCore;
  56. namespace WebKit {
  57. #ifndef NDEBUG
  58. #if OS(WINDOWS)
  59. static void sleep(unsigned seconds)
  60. {
  61. ::Sleep(seconds * 1000);
  62. }
  63. #endif
  64. #endif
  65. class EnvHttpProxyFactory : public QNetworkProxyFactory
  66. {
  67. public:
  68. EnvHttpProxyFactory() { }
  69. bool initializeFromEnvironment();
  70. QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery& query = QNetworkProxyQuery());
  71. private:
  72. QList<QNetworkProxy> m_httpProxy;
  73. QList<QNetworkProxy> m_httpsProxy;
  74. };
  75. bool EnvHttpProxyFactory::initializeFromEnvironment()
  76. {
  77. bool wasSetByEnvironment = false;
  78. QUrl proxyUrl = QUrl::fromUserInput(QString::fromLocal8Bit(qgetenv("http_proxy")));
  79. if (proxyUrl.isValid() && !proxyUrl.host().isEmpty()) {
  80. int proxyPort = (proxyUrl.port() > 0) ? proxyUrl.port() : 8080;
  81. m_httpProxy << QNetworkProxy(QNetworkProxy::HttpProxy, proxyUrl.host(), proxyPort);
  82. wasSetByEnvironment = true;
  83. } else
  84. m_httpProxy << QNetworkProxy::NoProxy;
  85. proxyUrl = QUrl::fromUserInput(QString::fromLocal8Bit(qgetenv("https_proxy")));
  86. if (proxyUrl.isValid() && !proxyUrl.host().isEmpty()) {
  87. int proxyPort = (proxyUrl.port() > 0) ? proxyUrl.port() : 8080;
  88. m_httpsProxy << QNetworkProxy(QNetworkProxy::HttpProxy, proxyUrl.host(), proxyPort);
  89. wasSetByEnvironment = true;
  90. } else
  91. m_httpsProxy << QNetworkProxy::NoProxy;
  92. return wasSetByEnvironment;
  93. }
  94. QList<QNetworkProxy> EnvHttpProxyFactory::queryProxy(const QNetworkProxyQuery& query)
  95. {
  96. QString protocol = query.protocolTag().toLower();
  97. bool localHost = false;
  98. if (!query.peerHostName().compare(QLatin1String("localhost"), Qt::CaseInsensitive) || !query.peerHostName().compare(QLatin1String("127.0.0.1"), Qt::CaseInsensitive))
  99. localHost = true;
  100. if (protocol == QLatin1String("http") && !localHost)
  101. return m_httpProxy;
  102. if (protocol == QLatin1String("https") && !localHost)
  103. return m_httpsProxy;
  104. QList<QNetworkProxy> proxies;
  105. proxies << QNetworkProxy::NoProxy;
  106. return proxies;
  107. }
  108. static void initializeProxy()
  109. {
  110. QList<QNetworkProxy> proxylist = QNetworkProxyFactory::systemProxyForQuery();
  111. if (proxylist.count() == 1) {
  112. QNetworkProxy proxy = proxylist.first();
  113. if (proxy == QNetworkProxy::NoProxy || proxy == QNetworkProxy::DefaultProxy) {
  114. EnvHttpProxyFactory* proxyFactory = new EnvHttpProxyFactory();
  115. if (proxyFactory->initializeFromEnvironment()) {
  116. QNetworkProxyFactory::setApplicationProxyFactory(proxyFactory);
  117. return;
  118. }
  119. }
  120. }
  121. QNetworkProxyFactory::setUseSystemConfiguration(true);
  122. }
  123. #if ENABLE(SUID_SANDBOX_LINUX)
  124. pid_t chrootMe()
  125. {
  126. // Get the file descriptor of the socketpair.
  127. char* sandboxSocketDescriptorString = getenv(SANDBOX_DESCRIPTOR);
  128. if (!sandboxSocketDescriptorString)
  129. return -1;
  130. char* firstInvalidCharacter;
  131. long int sandboxSocketDescriptor = strtol(sandboxSocketDescriptorString, &firstInvalidCharacter, 10);
  132. if (*firstInvalidCharacter != '\0') {
  133. fprintf(stderr, "The socket descriptor of sandbox is not valid.\n");
  134. return -1;
  135. }
  136. // Get the PID of the setuid helper.
  137. char* sandboxHelperPIDString = getenv(SANDBOX_HELPER_PID);
  138. pid_t sandboxHelperPID = -1;
  139. // If no PID is available, the default of -1 will do.
  140. if (sandboxHelperPIDString) {
  141. errno = 0;
  142. sandboxHelperPID = strtol(sandboxHelperPIDString, &firstInvalidCharacter, 10);
  143. if (*firstInvalidCharacter != '\0') {
  144. fprintf(stderr, "The PID of sandbox is not valid.\n");
  145. return -1;
  146. }
  147. }
  148. // Send the chrootMe message to the helper.
  149. char sandboxMeMessage = MSG_CHROOTME;
  150. ssize_t numberOfCharacters = write(sandboxSocketDescriptor, &sandboxMeMessage, 1);
  151. if (numberOfCharacters != 1) {
  152. fprintf(stderr, "ChrootMe msg failed to write: %s.\n", strerror(errno));
  153. return -1;
  154. }
  155. // Read the acknowledgement message from the helper.
  156. numberOfCharacters = read(sandboxSocketDescriptor, &sandboxMeMessage, 1);
  157. if (numberOfCharacters != 1 || sandboxMeMessage != MSG_CHROOTED) {
  158. fprintf(stderr, "Couldn't read the confirmation message: %s.\n", strerror(errno));
  159. return -1;
  160. }
  161. close(sandboxSocketDescriptor);
  162. // Wait for the helper process.
  163. int expectedPID = waitpid(sandboxHelperPID, 0, 0);
  164. if (expectedPID != -1 && (sandboxHelperPID == -1 || expectedPID == sandboxHelperPID))
  165. return expectedPID;
  166. fprintf(stderr, "Couldn't wait for the helper process: %s\n", strerror(errno));
  167. return -1;
  168. }
  169. #endif
  170. Q_DECL_EXPORT int WebProcessMainQt(QGuiApplication* app)
  171. {
  172. #if ENABLE(SUID_SANDBOX_LINUX)
  173. pid_t helper = chrootMe();
  174. if (helper == -1) {
  175. fprintf(stderr, "Asking for chroot failed.\n");
  176. return -1;
  177. }
  178. #endif
  179. initializeProxy();
  180. InitializeWebKit2();
  181. // Create the connection.
  182. if (app->arguments().size() <= 1) {
  183. qDebug() << "Error: wrong number of arguments.";
  184. return 1;
  185. }
  186. #if OS(DARWIN)
  187. QString serviceName = app->arguments().value(1);
  188. // Get the server port.
  189. mach_port_t identifier;
  190. kern_return_t kr = bootstrap_look_up2(bootstrap_port, serviceName.toUtf8().data(), &identifier, 0, 0);
  191. if (kr) {
  192. printf("bootstrap_look_up2 result: %x", kr);
  193. return 2;
  194. }
  195. #else
  196. bool wasNumber = false;
  197. qulonglong id = app->arguments().at(1).toULongLong(&wasNumber, 10);
  198. if (!wasNumber) {
  199. qDebug() << "Error: connection identifier wrong.";
  200. return 1;
  201. }
  202. CoreIPC::Connection::Identifier identifier;
  203. #if OS(WINDOWS)
  204. // Convert to HANDLE
  205. identifier = reinterpret_cast<CoreIPC::Connection::Identifier>(id);
  206. #else
  207. // Convert to int
  208. identifier = static_cast<CoreIPC::Connection::Identifier>(id);
  209. #endif
  210. #endif
  211. WebKit::ChildProcessInitializationParameters parameters;
  212. parameters.connectionIdentifier = identifier;
  213. WebKit::WebProcess::shared().initialize(parameters);
  214. RunLoop::run();
  215. // FIXME: Do more cleanup here.
  216. delete app;
  217. return 0;
  218. }
  219. }