diff options
Diffstat (limited to 'Source/WebKit2/UIProcess/Launcher')
12 files changed, 1330 insertions, 0 deletions
diff --git a/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.cpp b/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.cpp new file mode 100644 index 0000000..507edfa --- /dev/null +++ b/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ProcessLauncher.h" + +#include "WorkQueue.h" +#include <wtf/StdLibExtras.h> + +namespace WebKit { + +static WorkQueue& processLauncherWorkQueue() +{ + DEFINE_STATIC_LOCAL(WorkQueue, processLauncherWorkQueue, ("com.apple.WebKit.ProcessLauncher")); + return processLauncherWorkQueue; +} + +ProcessLauncher::ProcessLauncher(Client* client, const LaunchOptions& launchOptions) + : m_client(client) + , m_launchOptions(launchOptions) + , m_processIdentifier(0) +{ + // Launch the process. + m_isLaunching = true; + processLauncherWorkQueue().scheduleWork(WorkItem::create(this, &ProcessLauncher::launchProcess)); +} + +void ProcessLauncher::didFinishLaunchingProcess(PlatformProcessIdentifier processIdentifier, CoreIPC::Connection::Identifier identifier) +{ + m_processIdentifier = processIdentifier; + m_isLaunching = false; + + if (!m_client) { + // FIXME: Dispose of the connection identifier. + return; + } + + m_client->didFinishLaunching(this, identifier); +} + +void ProcessLauncher::invalidate() +{ + m_client = 0; + platformInvalidate(); +} + +const char* ProcessLauncher::processTypeAsString(ProcessType processType) +{ + switch (processType) { + case WebProcess: + return "webprocess"; + case PluginProcess: + return "pluginprocess"; + } + + ASSERT_NOT_REACHED(); + return 0; +} + +bool ProcessLauncher::getProcessTypeFromString(const char* string, ProcessType& processType) +{ + if (!strcmp(string, "webprocess")) { + processType = WebProcess; + return true; + } + + if (!strcmp(string, "pluginprocess")) { + processType = PluginProcess; + return true; + } + + return false; +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.h b/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.h new file mode 100644 index 0000000..31efd4d --- /dev/null +++ b/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebProcessLauncher_h +#define WebProcessLauncher_h + +#include "Connection.h" +#include "PlatformProcessIdentifier.h" +#include <wtf/RefPtr.h> +#include <wtf/Threading.h> + +#if PLATFORM(QT) +class QLocalSocket; +#endif + +namespace WebKit { + +class ProcessLauncher : public ThreadSafeShared<ProcessLauncher> { +public: + class Client { + public: + virtual ~Client() { } + + virtual void didFinishLaunching(ProcessLauncher*, CoreIPC::Connection::Identifier) = 0; + }; + + enum ProcessType { + WebProcess, + PluginProcess + }; + + struct LaunchOptions { + ProcessType processType; +#if PLATFORM(MAC) + static const cpu_type_t MatchCurrentArchitecture = 0; + cpu_type_t architecture; +#endif + }; + + static PassRefPtr<ProcessLauncher> create(Client* client, const LaunchOptions& launchOptions) + { + return adoptRef(new ProcessLauncher(client, launchOptions)); + } + + bool isLaunching() const { return m_isLaunching; } + PlatformProcessIdentifier processIdentifier() const { return m_processIdentifier; } + + void terminateProcess(); + void invalidate(); + + static bool getProcessTypeFromString(const char*, ProcessType&); + +#if PLATFORM(QT) + friend class ProcessLauncherHelper; + static QLocalSocket* takePendingConnection(); +#endif + +private: + ProcessLauncher(Client*, const LaunchOptions& launchOptions); + + static const char* processTypeAsString(ProcessType); + + void launchProcess(); + void didFinishLaunchingProcess(PlatformProcessIdentifier, CoreIPC::Connection::Identifier); + + void platformInvalidate(); + + Client* m_client; + + const LaunchOptions m_launchOptions; + bool m_isLaunching; + PlatformProcessIdentifier m_processIdentifier; +}; + +} // namespace WebKit + +#endif // WebProcessLauncher_h diff --git a/Source/WebKit2/UIProcess/Launcher/ThreadLauncher.cpp b/Source/WebKit2/UIProcess/Launcher/ThreadLauncher.cpp new file mode 100644 index 0000000..69e4893 --- /dev/null +++ b/Source/WebKit2/UIProcess/Launcher/ThreadLauncher.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ThreadLauncher.h" + +#include "RunLoop.h" + +namespace WebKit { + +ThreadLauncher::ThreadLauncher(Client* client) + : m_client(client) +{ + launchThread(); +} + +void ThreadLauncher::launchThread() +{ + m_isLaunching = true; + + CoreIPC::Connection::Identifier connectionIdentifier = createWebThread(); + + // We've finished launching the thread, message back to the main run loop. + RunLoop::main()->scheduleWork(WorkItem::create(this, &ThreadLauncher::didFinishLaunchingThread, connectionIdentifier)); +} + +void ThreadLauncher::didFinishLaunchingThread(CoreIPC::Connection::Identifier identifier) +{ + m_isLaunching = false; + + if (!m_client) { + // FIXME: Dispose of the connection identifier. + return; + } + + m_client->didFinishLaunching(this, identifier); +} + +void ThreadLauncher::invalidate() +{ + m_client = 0; +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Launcher/ThreadLauncher.h b/Source/WebKit2/UIProcess/Launcher/ThreadLauncher.h new file mode 100644 index 0000000..9c90fbd --- /dev/null +++ b/Source/WebKit2/UIProcess/Launcher/ThreadLauncher.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ThreadLauncher_h +#define ThreadLauncher_h + +#include "Connection.h" +#include "PlatformProcessIdentifier.h" +#include <wtf/RefPtr.h> +#include <wtf/Threading.h> + +#if PLATFORM(QT) +class QLocalSocket; +#endif + +namespace WebKit { + +class ThreadLauncher : public ThreadSafeShared<ThreadLauncher> { +public: + class Client { + public: + virtual ~Client() { } + virtual void didFinishLaunching(ThreadLauncher*, CoreIPC::Connection::Identifier) = 0; + }; + + static PassRefPtr<ThreadLauncher> create(Client* client) + { + return adoptRef(new ThreadLauncher(client)); + } + + bool isLaunching() const { return m_isLaunching; } + + void invalidate(); + +private: + explicit ThreadLauncher(Client*); + + void launchThread(); + void didFinishLaunchingThread(CoreIPC::Connection::Identifier); + + static CoreIPC::Connection::Identifier createWebThread(); + + bool m_isLaunching; + Client* m_client; +}; + +} // namespace WebKit + +#endif // ThreadLauncher_h diff --git a/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp b/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp new file mode 100644 index 0000000..2565a48 --- /dev/null +++ b/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY MOTOROLA INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ProcessLauncher.h" + +#include "Connection.h" +#include "RunLoop.h" +#include <WebCore/FileSystem.h> +#include <WebCore/ResourceHandle.h> +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <wtf/text/CString.h> +#include <wtf/text/WTFString.h> +#include <wtf/gobject/GOwnPtr.h> + +using namespace WebCore; + +namespace WebKit { + +const char* gWebKitWebProcessName = "WebKitWebProcess"; + +void ProcessLauncher::launchProcess() +{ + pid_t pid = 0; + + int sockets[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) { + fprintf(stderr, "Creation of socket failed with errno %d.\n", errno); + ASSERT_NOT_REACHED(); + return; + } + + pid = fork(); + if (!pid) { // child process + close(sockets[1]); + String socket = String::format("%d", sockets[0]); + GOwnPtr<gchar> binaryPath(g_build_filename(applicationDirectoryPath().data(), gWebKitWebProcessName, NULL)); + execl(binaryPath.get(), gWebKitWebProcessName, socket.utf8().data(), NULL); + } else if (pid > 0) { // parent process + close(sockets[0]); + m_processIdentifier = pid; + // We've finished launching the process, message back to the main run loop. + RunLoop::main()->scheduleWork(WorkItem::create(this, &ProcessLauncher::didFinishLaunchingProcess, pid, sockets[1])); + } else { + fprintf(stderr, "Unable to fork a new WebProcess with errno: %d.\n", errno); + ASSERT_NOT_REACHED(); + } +} + +void ProcessLauncher::terminateProcess() +{ + if (!m_processIdentifier) + return; + + kill(m_processIdentifier, SIGKILL); +} + +void ProcessLauncher::platformInvalidate() +{ +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Launcher/gtk/ThreadLauncherGtk.cpp b/Source/WebKit2/UIProcess/Launcher/gtk/ThreadLauncherGtk.cpp new file mode 100644 index 0000000..2841e0a --- /dev/null +++ b/Source/WebKit2/UIProcess/Launcher/gtk/ThreadLauncherGtk.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ThreadLauncher.h" + +#include "NotImplemented.h" + +namespace WebKit { + +CoreIPC::Connection::Identifier ThreadLauncher::createWebThread() +{ + notImplemented(); + return -1; +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Launcher/mac/ProcessLauncherMac.mm b/Source/WebKit2/UIProcess/Launcher/mac/ProcessLauncherMac.mm new file mode 100644 index 0000000..c285bae --- /dev/null +++ b/Source/WebKit2/UIProcess/Launcher/mac/ProcessLauncherMac.mm @@ -0,0 +1,311 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ProcessLauncher.h" + +#include "RunLoop.h" +#include "WebProcess.h" +#include "WebKitSystemInterface.h" +#include <crt_externs.h> +#include <mach-o/dyld.h> +#include <mach/machine.h> +#include <runtime/InitializeThreading.h> +#include <servers/bootstrap.h> +#include <spawn.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RetainPtr.h> +#include <wtf/Threading.h> +#include <wtf/text/CString.h> +#include <wtf/text/WTFString.h> + +using namespace WebCore; + +// FIXME: We should be doing this another way. +extern "C" kern_return_t bootstrap_register2(mach_port_t, name_t, mach_port_t, uint64_t); + +namespace WebKit { + +#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +static const char* processName() +{ + return [[[NSProcessInfo processInfo] processName] fileSystemRepresentation]; +} +#else +// -[NSProcessInfo processName] isn't thread-safe on Leopard and Snow Leopard so we have our own implementation. +static const char* createProcessName() +{ + uint32_t bufferSize = MAXPATHLEN; + char executablePath[bufferSize]; + + if (_NSGetExecutablePath(executablePath, &bufferSize)) + return ""; + + const char *processName = strrchr(executablePath, '/') + 1; + return strdup(processName); +} + +static const char* processName() +{ + static const char* processName = createProcessName(); + return processName; +} +#endif + +static void setUpTerminationNotificationHandler(pid_t pid) +{ +#if HAVE(DISPATCH_H) + dispatch_source_t processDiedSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, pid, DISPATCH_PROC_EXIT, dispatch_get_current_queue()); + dispatch_source_set_event_handler(processDiedSource, ^{ + int status; + waitpid(dispatch_source_get_handle(processDiedSource), &status, 0); + dispatch_source_cancel(processDiedSource); + }); + dispatch_source_set_cancel_handler(processDiedSource, ^{ + dispatch_release(processDiedSource); + }); + dispatch_resume(processDiedSource); +#endif +} + +class EnvironmentVariables { + WTF_MAKE_NONCOPYABLE(EnvironmentVariables); + +public: + EnvironmentVariables() + : m_environmentPointer(*_NSGetEnviron()) + { + } + + ~EnvironmentVariables() + { + deleteAllValues(m_allocatedStrings); + } + + void set(const char* name, const char* value) + { + // Check if we need to copy the environment. + if (m_environmentPointer == *_NSGetEnviron()) + copyEnvironmentVariables(); + + // Allocate a string for the name and value. + char* nameAndValue = createStringForVariable(name, value); + + for (size_t i = 0; i < m_environmentVariables.size() - 1; ++i) { + char* environmentVariable = m_environmentVariables[i]; + + if (valueIfVariableHasName(environmentVariable, name)) { + // Just replace the environment variable. + m_environmentVariables[i] = nameAndValue; + return; + } + } + + // Append the new string. + ASSERT(!m_environmentVariables.last()); + m_environmentVariables.last() = nameAndValue; + m_environmentVariables.append(static_cast<char*>(0)); + + m_environmentPointer = m_environmentVariables.data(); + } + + char* get(const char* name) const + { + for (size_t i = 0; m_environmentPointer[i]; ++i) { + if (char* value = valueIfVariableHasName(m_environmentPointer[i], name)) + return value; + } + return 0; + } + + // Will append the value with the given separator if the environment variable already exists. + void appendValue(const char* name, const char* value, char separator) + { + char* existingValue = get(name); + if (!existingValue) { + set(name, value); + return; + } + + Vector<char, 128> newValue; + newValue.append(existingValue, strlen(existingValue)); + newValue.append(separator); + newValue.append(value, strlen(value) + 1); + + set(name, newValue.data()); + } + + char** environmentPointer() const { return m_environmentPointer; } + +private: + char *valueIfVariableHasName(const char* environmentVariable, const char* name) const + { + // Find the environment variable name. + char* equalsLocation = strchr(environmentVariable, '='); + ASSERT(equalsLocation); + + size_t nameLength = equalsLocation - environmentVariable; + if (strncmp(environmentVariable, name, nameLength)) + return 0; + + return equalsLocation + 1; + } + + char* createStringForVariable(const char* name, const char* value) + { + int nameLength = strlen(name); + int valueLength = strlen(value); + + // Allocate enough room to hold 'name=value' and the null character. + char* string = static_cast<char*>(fastMalloc(nameLength + 1 + valueLength + 1)); + memcpy(string, name, nameLength); + string[nameLength] = '='; + memcpy(string + nameLength + 1, value, valueLength); + string[nameLength + 1 + valueLength] = '\0'; + + m_allocatedStrings.append(string); + + return string; + } + + void copyEnvironmentVariables() + { + for (size_t i = 0; (*_NSGetEnviron())[i]; i++) + m_environmentVariables.append((*_NSGetEnviron())[i]); + + // Null-terminate the array. + m_environmentVariables.append(static_cast<char*>(0)); + } + + char** m_environmentPointer; + Vector<char*> m_environmentVariables; + + // These allocated strings will be freed in the destructor. + Vector<char*> m_allocatedStrings; +}; + +void ProcessLauncher::launchProcess() +{ + // Create the listening port. + mach_port_t listeningPort; + mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort); + + // Insert a send right so we can send to it. + mach_port_insert_right(mach_task_self(), listeningPort, listeningPort, MACH_MSG_TYPE_MAKE_SEND); + + NSBundle *webKit2Bundle = [NSBundle bundleWithIdentifier:@"com.apple.WebKit2"]; + const char* bundlePath = [[webKit2Bundle executablePath] fileSystemRepresentation]; + + NSString *webProcessAppPath = [webKit2Bundle pathForAuxiliaryExecutable:@"WebProcess.app"]; + NSString *webProcessAppExecutablePath = [[NSBundle bundleWithPath:webProcessAppPath] executablePath]; + + // Make a unique, per pid, per process launcher web process service name. + CString serviceName = String::format("com.apple.WebKit.WebProcess-%d-%p", getpid(), this).utf8(); + + const char* path = [webProcessAppExecutablePath fileSystemRepresentation]; + const char* args[] = { path, bundlePath, "-type", processTypeAsString(m_launchOptions.processType), "-servicename", serviceName.data(), "-parentprocessname", processName(), 0 }; + + // Register ourselves. + kern_return_t kr = bootstrap_register2(bootstrap_port, const_cast<char*>(serviceName.data()), listeningPort, 0); + ASSERT_UNUSED(kr, kr == KERN_SUCCESS); + + posix_spawnattr_t attr; + posix_spawnattr_init(&attr); + + short flags = 0; + + // We want our process to receive all signals. + sigset_t signalMaskSet; + sigemptyset(&signalMaskSet); + + posix_spawnattr_setsigmask(&attr, &signalMaskSet); + flags |= POSIX_SPAWN_SETSIGMASK; + + // Determine the architecture to use. + cpu_type_t architecture = m_launchOptions.architecture; + if (architecture == LaunchOptions::MatchCurrentArchitecture) + architecture = _NSGetMachExecuteHeader()->cputype; + + cpu_type_t cpuTypes[] = { architecture }; + size_t outCount = 0; + posix_spawnattr_setbinpref_np(&attr, 1, cpuTypes, &outCount); + + // Start suspended so we can set up the termination notification handler. + flags |= POSIX_SPAWN_START_SUSPENDED; + + posix_spawnattr_setflags(&attr, flags); + + pid_t processIdentifier; + + EnvironmentVariables environmentVariables; + + if (m_launchOptions.processType == ProcessLauncher::PluginProcess) { + // We need to insert the plug-in process shim. + NSString *pluginProcessShimPathNSString = [[webProcessAppExecutablePath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"PluginProcessShim.dylib"]; + const char *pluginProcessShimPath = [pluginProcessShimPathNSString fileSystemRepresentation]; + + // Make sure that the file exists. + struct stat statBuf; + if (stat(pluginProcessShimPath, &statBuf) == 0 && (statBuf.st_mode & S_IFMT) == S_IFREG) + environmentVariables.appendValue("DYLD_INSERT_LIBRARIES", pluginProcessShimPath, ':'); + } + + int result = posix_spawn(&processIdentifier, path, 0, &attr, (char *const*)args, environmentVariables.environmentPointer()); + + posix_spawnattr_destroy(&attr); + + if (!result) { + // Set up the termination notification handler and then ask the child process to continue. + setUpTerminationNotificationHandler(processIdentifier); + kill(processIdentifier, SIGCONT); + } else { + // We failed to launch. Release the send right. + mach_port_deallocate(mach_task_self(), listeningPort); + + // And the receive right. + mach_port_mod_refs(mach_task_self(), listeningPort, MACH_PORT_RIGHT_RECEIVE, -1); + + listeningPort = MACH_PORT_NULL; + processIdentifier = 0; + } + + // We've finished launching the process, message back to the main run loop. + RunLoop::main()->scheduleWork(WorkItem::create(this, &ProcessLauncher::didFinishLaunchingProcess, processIdentifier, listeningPort)); +} + +void ProcessLauncher::terminateProcess() +{ + if (!m_processIdentifier) + return; + + kill(m_processIdentifier, SIGKILL); +} + +void ProcessLauncher::platformInvalidate() +{ +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Launcher/mac/ThreadLauncherMac.mm b/Source/WebKit2/UIProcess/Launcher/mac/ThreadLauncherMac.mm new file mode 100644 index 0000000..8aac275 --- /dev/null +++ b/Source/WebKit2/UIProcess/Launcher/mac/ThreadLauncherMac.mm @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ThreadLauncher.h" + +#include "RunLoop.h" +#include "WebProcess.h" +#include "WebSystemInterface.h" +#include <runtime/InitializeThreading.h> +#include <wtf/Threading.h> + +namespace WebKit { + +static void* webThreadBody(void* context) +{ + mach_port_t serverPort = static_cast<mach_port_t>(reinterpret_cast<uintptr_t>(context)); + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + InitWebCoreSystemInterface(); + JSC::initializeThreading(); + WTF::initializeMainThread(); + + WebProcess::shared().initialize(serverPort, RunLoop::current()); + + [pool drain]; + + RunLoop::current()->run(); + + return 0; +} + +CoreIPC::Connection::Identifier ThreadLauncher::createWebThread() +{ + // Create the service port. + mach_port_t listeningPort; + mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort); + + // Insert a send right so we can send to it. + mach_port_insert_right(mach_task_self(), listeningPort, listeningPort, MACH_MSG_TYPE_MAKE_SEND); + + if (!createThread(webThreadBody, reinterpret_cast<void*>(listeningPort), "WebKit2: WebThread")) { + mach_port_destroy(mach_task_self(), listeningPort); + return MACH_PORT_NULL; + } + + return listeningPort; +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp b/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp new file mode 100644 index 0000000..7dff894 --- /dev/null +++ b/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ProcessLauncher.h" + +#include "Connection.h" +#include "CleanupHandler.h" +#include "NotImplemented.h" +#include "RunLoop.h" +#include "WebProcess.h" +#include <runtime/InitializeThreading.h> +#include <string> +#include <wtf/HashSet.h> +#include <wtf/PassRefPtr.h> +#include <wtf/Threading.h> +#include <wtf/text/WTFString.h> + +#include <QApplication> +#include <QDebug> +#include <QFile> +#include <QLocalServer> +#include <QMetaType> +#include <QProcess> +#include <QString> + +#include <QtCore/qglobal.h> + +#include <sys/resource.h> +#include <unistd.h> + +using namespace WebCore; + +namespace WebKit { + +class ProcessLauncherHelper : public QObject { + Q_OBJECT +public: + ~ProcessLauncherHelper(); + void launch(WebKit::ProcessLauncher*); + QLocalSocket* takePendingConnection(); + static ProcessLauncherHelper* instance(); + + const QString serverName() const { return m_server.serverName(); } + +private: + ProcessLauncherHelper(); + QLocalServer m_server; + QList<WorkItem*> m_items; + + Q_SLOT void newConnection(); +}; + +Q_GLOBAL_STATIC(WTF::HashSet<QProcess*>, processes); + +static void cleanupAtExit() +{ + // Terminate our web process(es). + WTF::HashSet<QProcess*>::const_iterator end = processes()->end(); + for (WTF::HashSet<QProcess*>::const_iterator it = processes()->begin(); it != end; ++it) { + QProcess* process = *it; + process->disconnect(process); + process->terminate(); + if (!process->waitForFinished(200)) + process->kill(); + } + + // Do not leave the socket file behind. + QLocalServer::removeServer(ProcessLauncherHelper::instance()->serverName()); +} + +class QtWebProcess : public QProcess +{ + Q_OBJECT +public: + QtWebProcess(QObject* parent = 0) + : QProcess(parent) + { + static bool isRegistered = false; + if (!isRegistered) { + qRegisterMetaType<QProcess::ProcessState>("QProcess::ProcessState"); + isRegistered = true; + } + + connect(this, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(processStateChanged(QProcess::ProcessState))); + } + +private slots: + void processStateChanged(QProcess::ProcessState state); +}; + +void QtWebProcess::processStateChanged(QProcess::ProcessState state) +{ + QProcess* process = qobject_cast<QProcess*>(sender()); + if (!process) + return; + + if (state == QProcess::Running) + processes()->add(process); + else if (state == QProcess::NotRunning) + processes()->remove(process); +} + +void ProcessLauncherHelper::launch(WebKit::ProcessLauncher* launcher) +{ + QString applicationPath = "%1 %2"; + + if (QFile::exists(QCoreApplication::applicationDirPath() + "/QtWebProcess")) { + applicationPath = applicationPath.arg(QCoreApplication::applicationDirPath() + "/QtWebProcess"); + } else { + applicationPath = applicationPath.arg("QtWebProcess"); + } + + QString program(applicationPath.arg(m_server.serverName())); + + QProcess* webProcess = new QtWebProcess(); + webProcess->setProcessChannelMode(QProcess::ForwardedChannels); + webProcess->start(program); + + if (!webProcess->waitForStarted()) { + qDebug() << "Failed to start" << program; + ASSERT_NOT_REACHED(); + delete webProcess; + return; + } + + setpriority(PRIO_PROCESS, webProcess->pid(), 10); + + m_items.append(WorkItem::create(launcher, &WebKit::ProcessLauncher::didFinishLaunchingProcess, webProcess, m_server.serverName()).leakPtr()); +} + +QLocalSocket* ProcessLauncherHelper::takePendingConnection() +{ + return m_server.nextPendingConnection(); +} + +ProcessLauncherHelper::~ProcessLauncherHelper() +{ + m_server.close(); +} + +ProcessLauncherHelper::ProcessLauncherHelper() +{ + srandom(time(0)); + if (!m_server.listen("QtWebKit" + QString::number(random()))) { + qDebug() << "Failed to create server socket."; + ASSERT_NOT_REACHED(); + } + connect(&m_server, SIGNAL(newConnection()), this, SLOT(newConnection())); +} + +ProcessLauncherHelper* ProcessLauncherHelper::instance() +{ + static ProcessLauncherHelper* result = 0; + if (!result) { + result = new ProcessLauncherHelper(); + + // The purpose of the following line is to ensure that our static is initialized before the exit handler is installed. + processes()->clear(); + + atexit(cleanupAtExit); + } + return result; +} + +void ProcessLauncherHelper::newConnection() +{ + ASSERT(!m_items.isEmpty()); + + m_items[0]->execute(); + delete m_items[0]; + m_items.pop_front(); +} + +void ProcessLauncher::launchProcess() +{ + ProcessLauncherHelper::instance()->launch(this); +} + +void ProcessLauncher::terminateProcess() +{ + if (!m_processIdentifier) + return; + + QObject::connect(m_processIdentifier, SIGNAL(finished(int)), m_processIdentifier, SLOT(deleteLater()), Qt::QueuedConnection); + m_processIdentifier->terminate(); +} + +QLocalSocket* ProcessLauncher::takePendingConnection() +{ + return ProcessLauncherHelper::instance()->takePendingConnection(); +} + +void ProcessLauncher::platformInvalidate() +{ + notImplemented(); +} + +} // namespace WebKit + +#include "ProcessLauncherQt.moc" diff --git a/Source/WebKit2/UIProcess/Launcher/qt/ThreadLauncherQt.cpp b/Source/WebKit2/UIProcess/Launcher/qt/ThreadLauncherQt.cpp new file mode 100644 index 0000000..471a424 --- /dev/null +++ b/Source/WebKit2/UIProcess/Launcher/qt/ThreadLauncherQt.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ThreadLauncher.h" + +#include "RunLoop.h" +#include "WebProcess.h" +#include <runtime/InitializeThreading.h> +#include <wtf/Threading.h> + +#include <QApplication> +#include <QDebug> +#include <QFile> +#include <QLocalServer> +#include <QProcess> + +#include <QtCore/qglobal.h> + +#include <sys/resource.h> +#include <unistd.h> + +using namespace WebCore; + +namespace WebKit { + +static void* webThreadBody(void* /* context */) +{ + // Initialization + JSC::initializeThreading(); + WTF::initializeMainThread(); + + // FIXME: We do not support threaded mode for now. + + WebProcess::shared().initialize("foo", RunLoop::current()); + RunLoop::run(); + + return 0; +} + +CoreIPC::Connection::Identifier ThreadLauncher::createWebThread() +{ + srandom(time(0)); + int connectionIdentifier = random(); + + if (!createThread(webThreadBody, reinterpret_cast<void*>(connectionIdentifier), "WebKit2: WebThread")) { + qWarning() << "failed starting thread"; + return 0; + } + + QString serverIdentifier = QString::number(connectionIdentifier); + return serverIdentifier; +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Launcher/win/ProcessLauncherWin.cpp b/Source/WebKit2/UIProcess/Launcher/win/ProcessLauncherWin.cpp new file mode 100644 index 0000000..7165a18 --- /dev/null +++ b/Source/WebKit2/UIProcess/Launcher/win/ProcessLauncherWin.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ProcessLauncher.h" + +#include "Connection.h" +#include "RunLoop.h" +#include <shlwapi.h> +#include <wtf/text/WTFString.h> + +#ifdef DEBUG_ALL +const LPCWSTR webProcessName = L"WebKit2WebProcess_debug.exe"; +#else +const LPCWSTR webProcessName = L"WebKit2WebProcess.exe"; +#endif + +#ifdef DEBUG_ALL +const LPCWSTR webKitDLLName = L"WebKit_debug.dll"; +#else +const LPCWSTR webKitDLLName = L"WebKit.dll"; +#endif + +namespace WebKit { + +void ProcessLauncher::launchProcess() +{ + // First, create the server and client identifiers. + HANDLE serverIdentifier, clientIdentifier; + if (!CoreIPC::Connection::createServerAndClientIdentifiers(serverIdentifier, clientIdentifier)) { + // FIXME: What should we do here? + ASSERT_NOT_REACHED(); + } + + // Ensure that the child process inherits the client identifier. + ::SetHandleInformation(clientIdentifier, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); + + // To get the full file path to WebKit2WebProcess.exe, we fild the location of WebKit.dll, + // remove the last path component, and then append WebKit2WebProcess(_debug).exe. + HMODULE webKitModule = ::GetModuleHandleW(webKitDLLName); + ASSERT(webKitModule); + if (!webKitModule) + return; + + WCHAR pathStr[MAX_PATH]; + if (!::GetModuleFileNameW(webKitModule, pathStr, WTF_ARRAY_LENGTH(pathStr))) + return; + + ::PathRemoveFileSpecW(pathStr); + if (!::PathAppendW(pathStr, webProcessName)) + return; + + String commandLine(pathStr); + + // FIXME: It would be nice if we could just create a CommandLine object and output a command line vector from it. + Vector<UChar> commandLineVector; + append(commandLineVector, commandLine); + append(commandLineVector, " -type webprocess"); + append(commandLineVector, " -clientIdentifier "); + append(commandLineVector, String::number(reinterpret_cast<uintptr_t>(clientIdentifier))); + commandLineVector.append('\0'); + + STARTUPINFO startupInfo = { 0 }; + startupInfo.cb = sizeof(startupInfo); + PROCESS_INFORMATION processInformation = { 0 }; + BOOL result = ::CreateProcessW(0, commandLineVector.data(), 0, 0, true, 0, 0, 0, &startupInfo, &processInformation); + + // We can now close the client identifier handle. + ::CloseHandle(clientIdentifier); + + if (!result) { + // FIXME: What should we do here? + DWORD error = ::GetLastError(); + ASSERT_NOT_REACHED(); + } + + // Don't leak the thread handle. + ::CloseHandle(processInformation.hThread); + + // We've finished launching the process, message back to the run loop. + RunLoop::main()->scheduleWork(WorkItem::create(this, &ProcessLauncher::didFinishLaunchingProcess, processInformation.hProcess, serverIdentifier)); +} + +void ProcessLauncher::terminateProcess() +{ + if (!m_processIdentifier) + return; + + ::TerminateProcess(m_processIdentifier, 0); +} + +void ProcessLauncher::platformInvalidate() +{ + if (!m_processIdentifier) + return; + + ::CloseHandle(m_processIdentifier); + m_processIdentifier = 0; +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Launcher/win/ThreadLauncherWin.cpp b/Source/WebKit2/UIProcess/Launcher/win/ThreadLauncherWin.cpp new file mode 100644 index 0000000..b8b2f64 --- /dev/null +++ b/Source/WebKit2/UIProcess/Launcher/win/ThreadLauncherWin.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ThreadLauncher.h" + +#include "RunLoop.h" +#include "WebProcess.h" +#include <runtime/InitializeThreading.h> +#include <wtf/Threading.h> + +using namespace WebCore; + +namespace WebKit { + +static void* webThreadBody(void* context) +{ + HANDLE clientIdentifier = reinterpret_cast<HANDLE>(context); + + // Initialization + JSC::initializeThreading(); + WTF::initializeMainThread(); + + WebProcess::shared().initialize(clientIdentifier, RunLoop::current()); + RunLoop::run(); + + return 0; +} + +CoreIPC::Connection::Identifier ThreadLauncher::createWebThread() +{ + // First, create the server and client identifiers. + HANDLE serverIdentifier, clientIdentifier; + if (!CoreIPC::Connection::createServerAndClientIdentifiers(serverIdentifier, clientIdentifier)) { + // FIXME: What should we do here? + ASSERT_NOT_REACHED(); + } + + if (!createThread(webThreadBody, reinterpret_cast<void*>(clientIdentifier), "WebKit2: WebThread")) { + ::CloseHandle(serverIdentifier); + ::CloseHandle(clientIdentifier); + return 0; + } + + return serverIdentifier; +} + +} // namespace WebKit |