Use xpc_connection_kill for killing child processes where appropriate
[WebKit-https.git] / Source / WebKit2 / Shared / ChildProcessProxy.cpp
1 /*
2  * Copyright (C) 2012 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 "ChildProcessProxy.h"
28
29 #include <wtf/RunLoop.h>
30
31 namespace WebKit {
32
33 ChildProcessProxy::ChildProcessProxy()
34 {
35 }
36
37 ChildProcessProxy::~ChildProcessProxy()
38 {
39     if (m_connection)
40         m_connection->invalidate();
41
42     if (m_processLauncher) {
43         m_processLauncher->invalidate();
44         m_processLauncher = 0;
45     }
46 }
47
48 ChildProcessProxy* ChildProcessProxy::fromConnection(IPC::Connection* connection)
49 {
50     ASSERT(connection);
51
52     ChildProcessProxy* childProcessProxy = static_cast<ChildProcessProxy*>(connection->client());
53     ASSERT(childProcessProxy->connection() == connection);
54
55     return childProcessProxy;
56 }
57
58 void ChildProcessProxy::connect()
59 {
60     ASSERT(!m_processLauncher);
61     ProcessLauncher::LaunchOptions launchOptions;
62     getLaunchOptions(launchOptions);
63     m_processLauncher = ProcessLauncher::create(this, launchOptions);
64 }
65
66 void ChildProcessProxy::terminate()
67 {
68     if (m_connection && m_connection->kill())
69         return;
70
71     // FIXME: We should really merge process launching into IPC connection creation and get rid of the process launcher.
72     if (m_processLauncher)
73         m_processLauncher->terminateProcess();
74 }
75
76 ChildProcessProxy::State ChildProcessProxy::state() const
77 {
78     if (m_processLauncher && m_processLauncher->isLaunching())
79         return ChildProcessProxy::State::Launching;
80
81     if (!m_connection)
82         return ChildProcessProxy::State::Terminated;
83
84     return ChildProcessProxy::State::Running;
85 }
86
87 bool ChildProcessProxy::sendMessage(std::unique_ptr<IPC::MessageEncoder> encoder, unsigned messageSendFlags)
88 {
89     switch (state()) {
90     case State::Launching:
91         // If we're waiting for the child process to launch, we need to stash away the messages so we can send them once we have a connection.
92         m_pendingMessages.append(std::make_pair(std::move(encoder), messageSendFlags));
93         return true;
94
95     case State::Running:
96         return connection()->sendMessage(std::move(encoder), messageSendFlags);
97
98     case State::Terminated:
99         return false;
100     }
101
102     return false;
103 }
104
105 void ChildProcessProxy::addMessageReceiver(IPC::StringReference messageReceiverName, IPC::MessageReceiver& messageReceiver)
106 {
107     m_messageReceiverMap.addMessageReceiver(messageReceiverName, messageReceiver);
108 }
109
110 void ChildProcessProxy::addMessageReceiver(IPC::StringReference messageReceiverName, uint64_t destinationID, IPC::MessageReceiver& messageReceiver)
111 {
112     m_messageReceiverMap.addMessageReceiver(messageReceiverName, destinationID, messageReceiver);
113 }
114
115 void ChildProcessProxy::removeMessageReceiver(IPC::StringReference messageReceiverName, uint64_t destinationID)
116 {
117     m_messageReceiverMap.removeMessageReceiver(messageReceiverName, destinationID);
118 }
119
120 bool ChildProcessProxy::dispatchMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder)
121 {
122     return m_messageReceiverMap.dispatchMessage(connection, decoder);
123 }
124
125 bool ChildProcessProxy::dispatchSyncMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder)
126 {
127     return m_messageReceiverMap.dispatchSyncMessage(connection, decoder, replyEncoder);
128 }
129
130 void ChildProcessProxy::didFinishLaunching(ProcessLauncher*, IPC::Connection::Identifier connectionIdentifier)
131 {
132     ASSERT(!m_connection);
133
134     m_connection = IPC::Connection::createServerConnection(connectionIdentifier, this, RunLoop::main());
135 #if PLATFORM(MAC)
136     m_connection->setShouldCloseConnectionOnMachExceptions();
137 #endif
138
139     for (size_t i = 0; i < m_pendingMessages.size(); ++i) {
140         std::unique_ptr<IPC::MessageEncoder> message = std::move(m_pendingMessages[i].first);
141         unsigned messageSendFlags = m_pendingMessages[i].second;
142         m_connection->sendMessage(std::move(message), messageSendFlags);
143     }
144
145     connectionWillOpen(m_connection.get());
146     m_connection->open();
147
148     m_pendingMessages.clear();
149 }
150
151 void ChildProcessProxy::abortProcessLaunchIfNeeded()
152 {
153     if (state() != State::Launching)
154         return;
155
156     m_processLauncher->invalidate();
157     m_processLauncher = nullptr;
158 }
159
160 void ChildProcessProxy::clearConnection()
161 {
162     if (!m_connection)
163         return;
164
165     connectionWillClose(m_connection.get());
166
167     m_connection->invalidate();
168     m_connection = nullptr;
169 }
170
171 void ChildProcessProxy::connectionWillOpen(IPC::Connection*)
172 {
173 }
174
175 void ChildProcessProxy::connectionWillClose(IPC::Connection*)
176 {
177 }
178
179 } // namespace WebKit