2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
4 * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25 * THE POSSIBILITY OF SUCH DAMAGE.
31 #include "Arguments.h"
32 #include "MessageDecoder.h"
33 #include "MessageEncoder.h"
34 #include "MessageReceiver.h"
35 #include "ProcessType.h"
37 #include <condition_variable>
38 #include <wtf/Deque.h>
39 #include <wtf/Forward.h>
40 #include <wtf/HashMap.h>
41 #include <wtf/WorkQueue.h>
42 #include <wtf/text/CString.h>
45 #include <mach/mach_port.h>
46 #include <wtf/OSObjectPtr.h>
47 #include <wtf/spi/darwin/XPCSPI.h>
50 #if PLATFORM(GTK) || PLATFORM(EFL)
51 #include "PlatformProcessIdentifier.h"
60 struct WaitForMessageState;
62 enum MessageSendFlags {
63 // Whether this message should be dispatched when waiting for a sync reply.
64 // This is the default for synchronous messages.
65 DispatchMessageEvenWhenWaitingForSyncReply = 1 << 0,
68 enum SyncMessageSendFlags {
69 // Use this to inform that this sync call will suspend this process until the user responds with input.
70 InformPlatformProcessWillSuspend = 1 << 0,
71 // Some platform accessibility clients can't suspend gracefully and need to spin the run loop so WebProcess doesn't hang.
72 // FIXME (126021): Remove when no platforms need to support this.
73 SpinRunLoopWhileWaitingForReply = 1 << 1,
76 enum WaitForMessageFlags {
77 // Use this to make waitForMessage be interrupted immediately by any incoming sync messages.
78 InterruptWaitingIfSyncMessageArrives = 1 << 0,
81 #define MESSAGE_CHECK_BASE(assertion, connection) do \
84 (connection)->markCurrentlyDispatchedMessageAsInvalid(); \
89 class Connection : public ThreadSafeRefCounted<Connection> {
91 class Client : public MessageReceiver {
93 virtual void didClose(Connection&) = 0;
94 virtual void didReceiveInvalidMessage(Connection&, StringReference messageReceiverName, StringReference messageName) = 0;
95 virtual IPC::ProcessType localProcessType() = 0;
96 virtual IPC::ProcessType remoteProcessType() = 0;
102 class WorkQueueMessageReceiver : public MessageReceiver, public ThreadSafeRefCounted<WorkQueueMessageReceiver> {
108 : port(MACH_PORT_NULL)
112 Identifier(mach_port_t port)
117 Identifier(mach_port_t port, OSObjectPtr<xpc_connection_t> xpcConnection)
119 , xpcConnection(WTF::move(xpcConnection))
124 OSObjectPtr<xpc_connection_t> xpcConnection;
126 static bool identifierIsNull(Identifier identifier) { return identifier.port == MACH_PORT_NULL; }
127 xpc_connection_t xpcConnection() const { return m_xpcConnection.get(); }
128 bool getAuditToken(audit_token_t&);
129 pid_t remoteProcessID() const;
130 #elif USE(UNIX_DOMAIN_SOCKETS)
131 typedef int Identifier;
132 static bool identifierIsNull(Identifier identifier) { return !identifier; }
139 enum ConnectionOptions {
140 SetCloexecOnClient = 1 << 0,
141 SetCloexecOnServer = 1 << 1,
144 static Connection::SocketPair createPlatformConnection(unsigned options = SetCloexecOnClient | SetCloexecOnServer);
147 static Ref<Connection> createServerConnection(Identifier, Client&, WTF::RunLoop& clientRunLoop);
148 static Ref<Connection> createClientConnection(Identifier, Client&, WTF::RunLoop& clientRunLoop);
151 Client* client() const { return m_client; }
154 void setShouldCloseConnectionOnMachExceptions();
157 void setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(bool);
158 void setShouldExitOnSyncMessageSendFailure(bool shouldExitOnSyncMessageSendFailure);
160 // The set callback will be called on the connection work queue when the connection is closed,
161 // before didCall is called on the client thread. Must be called before the connection is opened.
162 // In the future we might want a more generic way to handle sync or async messages directly
163 // on the work queue, for example if we want to handle them on some other thread we could avoid
164 // handling the message on the client thread first.
165 typedef void (*DidCloseOnConnectionWorkQueueCallback)(Connection*);
166 void setDidCloseOnConnectionWorkQueueCallback(DidCloseOnConnectionWorkQueueCallback callback);
168 void addWorkQueueMessageReceiver(StringReference messageReceiverName, WorkQueue*, WorkQueueMessageReceiver*);
169 void removeWorkQueueMessageReceiver(StringReference messageReceiverName);
173 void markCurrentlyDispatchedMessageAsInvalid();
175 void postConnectionDidCloseOnConnectionWorkQueue();
177 template<typename T> bool send(T&& message, uint64_t destinationID, unsigned messageSendFlags = 0);
178 template<typename T> bool sendSync(T&& message, typename T::Reply&& reply, uint64_t destinationID, std::chrono::milliseconds timeout = std::chrono::milliseconds::max(), unsigned syncSendFlags = 0);
179 template<typename T> bool waitForAndDispatchImmediately(uint64_t destinationID, std::chrono::milliseconds timeout, unsigned waitForMessageFlags = 0);
181 std::unique_ptr<MessageEncoder> createSyncMessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, uint64_t& syncRequestID);
182 bool sendMessage(std::unique_ptr<MessageEncoder>, unsigned messageSendFlags = 0, bool alreadyRecordedMessage = false);
183 std::unique_ptr<MessageDecoder> sendSyncMessage(uint64_t syncRequestID, std::unique_ptr<MessageEncoder>, std::chrono::milliseconds timeout, unsigned syncSendFlags = 0);
184 std::unique_ptr<MessageDecoder> sendSyncMessageFromSecondaryThread(uint64_t syncRequestID, std::unique_ptr<MessageEncoder>, std::chrono::milliseconds timeout);
185 bool sendSyncReply(std::unique_ptr<MessageEncoder>);
187 void wakeUpRunLoop();
189 void incrementDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount() { ++m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount; }
190 void decrementDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount() { --m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount; }
192 bool inSendSync() const { return m_inSendSyncCount; }
194 Identifier identifier() const;
198 void terminateSoon(double intervalInSeconds);
201 bool isValid() const { return m_client; }
204 Connection(Identifier, bool isServer, Client&, WTF::RunLoop& clientRunLoop);
205 void platformInitialize(Identifier);
206 void platformInvalidate();
208 std::unique_ptr<MessageDecoder> waitForMessage(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, std::chrono::milliseconds timeout, unsigned waitForMessageFlags);
210 std::unique_ptr<MessageDecoder> waitForSyncReply(uint64_t syncRequestID, std::chrono::milliseconds timeout, unsigned syncSendFlags);
212 // Called on the connection work queue.
213 void processIncomingMessage(std::unique_ptr<MessageDecoder>);
214 void processIncomingSyncReply(std::unique_ptr<MessageDecoder>);
216 void dispatchWorkQueueMessageReceiverMessage(WorkQueueMessageReceiver*, MessageDecoder*);
218 bool canSendOutgoingMessages() const;
219 bool platformCanSendOutgoingMessages() const;
220 void sendOutgoingMessages();
221 bool sendOutgoingMessage(std::unique_ptr<MessageEncoder>);
222 void connectionDidClose();
224 // Called on the listener thread.
225 void dispatchOneMessage();
226 void dispatchMessage(std::unique_ptr<MessageDecoder>);
227 void dispatchMessage(MessageDecoder&);
228 void dispatchSyncMessage(MessageDecoder&);
229 void dispatchDidReceiveInvalidMessage(const CString& messageReceiverNameString, const CString& messageNameString);
230 void didFailToSendSyncMessage();
232 // Can be called on any thread.
233 void enqueueIncomingMessage(std::unique_ptr<MessageDecoder>);
235 void willSendSyncMessage(unsigned syncSendFlags);
236 void didReceiveSyncReply(unsigned syncSendFlags);
240 std::atomic<uint64_t> m_syncRequestID;
242 bool m_onlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage;
243 bool m_shouldExitOnSyncMessageSendFailure;
244 DidCloseOnConnectionWorkQueueCallback m_didCloseOnConnectionWorkQueueCallback;
247 Ref<WorkQueue> m_connectionQueue;
248 WTF::RunLoop& m_clientRunLoop;
250 HashMap<StringReference, std::pair<RefPtr<WorkQueue>, RefPtr<WorkQueueMessageReceiver>>> m_workQueueMessageReceivers;
252 unsigned m_inSendSyncCount;
253 unsigned m_inDispatchMessageCount;
254 unsigned m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount;
255 bool m_didReceiveInvalidMessage;
257 // Incoming messages.
258 std::mutex m_incomingMessagesMutex;
259 Deque<std::unique_ptr<MessageDecoder>> m_incomingMessages;
261 // Outgoing messages.
262 std::mutex m_outgoingMessagesMutex;
263 Deque<std::unique_ptr<MessageEncoder>> m_outgoingMessages;
265 std::condition_variable m_waitForMessageCondition;
266 std::mutex m_waitForMessageMutex;
268 WaitForMessageState* m_waitingForMessage;
270 // Represents a sync request for which we're waiting on a reply.
271 struct PendingSyncReply {
273 uint64_t syncRequestID;
275 // The reply decoder, will be null if there was an error processing the sync
276 // message on the other side.
277 std::unique_ptr<MessageDecoder> replyDecoder;
279 // Will be set to true once a reply has been received.
280 bool didReceiveReply;
284 , didReceiveReply(false)
288 explicit PendingSyncReply(uint64_t syncRequestID)
289 : syncRequestID(syncRequestID)
295 class SyncMessageState;
296 friend class SyncMessageState;
297 RefPtr<SyncMessageState> m_syncMessageState;
299 Mutex m_syncReplyStateMutex;
300 bool m_shouldWaitForSyncReplies;
301 Vector<PendingSyncReply> m_pendingSyncReplies;
303 class SecondaryThreadPendingSyncReply;
304 typedef HashMap<uint64_t, SecondaryThreadPendingSyncReply*> SecondaryThreadPendingSyncReplyMap;
305 SecondaryThreadPendingSyncReplyMap m_secondaryThreadPendingSyncReplyMap;
308 // Called on the connection queue.
309 void receiveSourceEventHandler();
310 void initializeDeadNameSource();
312 mach_port_t m_sendPort;
313 dispatch_source_t m_deadNameSource;
315 mach_port_t m_receivePort;
316 dispatch_source_t m_receivePortDataAvailableSource;
319 void exceptionSourceEventHandler();
321 // If setShouldCloseConnectionOnMachExceptions has been called, this has
322 // the exception port that exceptions from the other end will be sent on.
323 mach_port_t m_exceptionPort;
324 dispatch_source_t m_exceptionPortDataAvailableSource;
327 OSObjectPtr<xpc_connection_t> m_xpcConnection;
329 #elif USE(UNIX_DOMAIN_SOCKETS)
330 // Called on the connection queue.
331 void readyReadHandler();
332 bool processMessage();
334 Vector<uint8_t> m_readBuffer;
335 size_t m_readBufferSize;
336 Vector<int> m_fileDescriptors;
337 size_t m_fileDescriptorsSize;
338 int m_socketDescriptor;
342 template<typename T> bool Connection::send(T&& message, uint64_t destinationID, unsigned messageSendFlags)
344 COMPILE_ASSERT(!T::isSync, AsyncMessageExpected);
346 auto encoder = std::make_unique<MessageEncoder>(T::receiverName(), T::name(), destinationID);
347 encoder->encode(message.arguments());
349 return sendMessage(WTF::move(encoder), messageSendFlags);
352 template<typename T> bool Connection::sendSync(T&& message, typename T::Reply&& reply, uint64_t destinationID, std::chrono::milliseconds timeout, unsigned syncSendFlags)
354 COMPILE_ASSERT(T::isSync, SyncMessageExpected);
356 uint64_t syncRequestID = 0;
357 std::unique_ptr<MessageEncoder> encoder = createSyncMessageEncoder(T::receiverName(), T::name(), destinationID, syncRequestID);
359 // Encode the rest of the input arguments.
360 encoder->encode(message.arguments());
362 // Now send the message and wait for a reply.
363 std::unique_ptr<MessageDecoder> replyDecoder = sendSyncMessage(syncRequestID, WTF::move(encoder), timeout, syncSendFlags);
368 return replyDecoder->decode(reply);
371 template<typename T> bool Connection::waitForAndDispatchImmediately(uint64_t destinationID, std::chrono::milliseconds timeout, unsigned waitForMessageFlags)
373 std::unique_ptr<MessageDecoder> decoder = waitForMessage(T::receiverName(), T::name(), destinationID, timeout, waitForMessageFlags);
377 ASSERT(decoder->destinationID() == destinationID);
378 m_client->didReceiveMessage(*this, *decoder);
384 #endif // Connection_h