8064e4bca4ab43a3a668b252d4d78139f98a24e5
[WebKit-https.git] / Source / WebKit2 / Platform / IPC / Connection.h
1 /*
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.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
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.
14  *
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.
26  */
27
28 #ifndef Connection_h
29 #define Connection_h
30
31 #include "Arguments.h"
32 #include "MessageDecoder.h"
33 #include "MessageEncoder.h"
34 #include "MessageReceiver.h"
35 #include "WorkQueue.h"
36 #include <atomic>
37 #include <condition_variable>
38 #include <wtf/Deque.h>
39 #include <wtf/Forward.h>
40 #include <wtf/PassRefPtr.h>
41 #include <wtf/text/CString.h>
42
43 #if OS(DARWIN)
44 #include "XPCPtr.h"
45 #include <mach/mach_port.h>
46 #endif
47
48 #if PLATFORM(GTK) || PLATFORM(EFL)
49 #include "PlatformProcessIdentifier.h"
50 #endif
51
52 namespace WTF {
53 class RunLoop;
54 }
55
56 namespace IPC {
57
58 enum MessageSendFlags {
59     // Whether this message should be dispatched when waiting for a sync reply.
60     // This is the default for synchronous messages.
61     DispatchMessageEvenWhenWaitingForSyncReply = 1 << 0,
62 };
63
64 enum SyncMessageSendFlags {
65     // Use this to inform that this sync call will suspend this process until the user responds with input.
66     InformPlatformProcessWillSuspend = 1 << 0,
67     // Some platform accessibility clients can't suspend gracefully and need to spin the run loop so WebProcess doesn't hang.
68     // FIXME (126021): Remove when no platforms need to support this.
69     SpinRunLoopWhileWaitingForReply = 1 << 1,
70 };
71     
72 #define MESSAGE_CHECK_BASE(assertion, connection) do \
73     if (!(assertion)) { \
74         ASSERT(assertion); \
75         (connection)->markCurrentlyDispatchedMessageAsInvalid(); \
76         return; \
77     } \
78 while (0)
79
80 class Connection : public ThreadSafeRefCounted<Connection> {
81 public:
82     class Client : public MessageReceiver {
83     public:
84         virtual void didClose(Connection*) = 0;
85         virtual void didReceiveInvalidMessage(Connection*, StringReference messageReceiverName, StringReference messageName) = 0;
86
87     protected:
88         virtual ~Client() { }
89     };
90
91     class WorkQueueMessageReceiver : public MessageReceiver, public ThreadSafeRefCounted<WorkQueueMessageReceiver> {
92     };
93
94 #if OS(DARWIN)
95     struct Identifier {
96         Identifier()
97             : port(MACH_PORT_NULL)
98         {
99         }
100
101         Identifier(mach_port_t port)
102             : port(port)
103         {
104         }
105
106         Identifier(mach_port_t port, XPCPtr<xpc_connection_t> xpcConnection)
107             : port(port)
108             , xpcConnection(std::move(xpcConnection))
109         {
110         }
111
112         mach_port_t port;
113         XPCPtr<xpc_connection_t> xpcConnection;
114     };
115     static bool identifierIsNull(Identifier identifier) { return identifier.port == MACH_PORT_NULL; }
116     xpc_connection_t xpcConnection() { return m_xpcConnection.get(); }
117     bool getAuditToken(audit_token_t&);
118 #elif USE(UNIX_DOMAIN_SOCKETS)
119     typedef int Identifier;
120     static bool identifierIsNull(Identifier identifier) { return !identifier; }
121
122     struct SocketPair {
123         int client;
124         int server;
125     };
126
127     enum ConnectionOptions {
128         SetCloexecOnClient = 1 << 0,
129         SetCloexecOnServer = 1 << 1,
130     };
131
132     static Connection::SocketPair createPlatformConnection(unsigned options = SetCloexecOnClient | SetCloexecOnServer);
133 #endif
134
135     static PassRefPtr<Connection> createServerConnection(Identifier, Client*, WTF::RunLoop& clientRunLoop);
136     static PassRefPtr<Connection> createClientConnection(Identifier, Client*, WTF::RunLoop& clientRunLoop);
137     ~Connection();
138
139     Client* client() const { return m_client; }
140
141 #if PLATFORM(MAC)
142     void setShouldCloseConnectionOnMachExceptions();
143 #endif
144
145     void setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(bool);
146     void setShouldExitOnSyncMessageSendFailure(bool shouldExitOnSyncMessageSendFailure);
147
148     // The set callback will be called on the connection work queue when the connection is closed, 
149     // before didCall is called on the client thread. Must be called before the connection is opened.
150     // In the future we might want a more generic way to handle sync or async messages directly
151     // on the work queue, for example if we want to handle them on some other thread we could avoid
152     // handling the message on the client thread first.
153     typedef void (*DidCloseOnConnectionWorkQueueCallback)(Connection*);
154     void setDidCloseOnConnectionWorkQueueCallback(DidCloseOnConnectionWorkQueueCallback callback);
155
156     void addWorkQueueMessageReceiver(StringReference messageReceiverName, WorkQueue*, WorkQueueMessageReceiver*);
157     void removeWorkQueueMessageReceiver(StringReference messageReceiverName);
158
159     bool open();
160     void invalidate();
161     void markCurrentlyDispatchedMessageAsInvalid();
162
163     void postConnectionDidCloseOnConnectionWorkQueue();
164
165     template<typename T> bool send(T&& message, uint64_t destinationID, unsigned messageSendFlags = 0);
166     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);
167     template<typename T> bool waitForAndDispatchImmediately(uint64_t destinationID, std::chrono::milliseconds timeout);
168
169     std::unique_ptr<MessageEncoder> createSyncMessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, uint64_t& syncRequestID);
170     bool sendMessage(std::unique_ptr<MessageEncoder>, unsigned messageSendFlags = 0);
171     std::unique_ptr<MessageDecoder> sendSyncMessage(uint64_t syncRequestID, std::unique_ptr<MessageEncoder>, std::chrono::milliseconds timeout, unsigned syncSendFlags = 0);
172     std::unique_ptr<MessageDecoder> sendSyncMessageFromSecondaryThread(uint64_t syncRequestID, std::unique_ptr<MessageEncoder>, std::chrono::milliseconds timeout);
173     bool sendSyncReply(std::unique_ptr<MessageEncoder>);
174
175     void wakeUpRunLoop();
176
177     void incrementDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount() { ++m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount; }
178     void decrementDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount() { --m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount; }
179
180     bool inSendSync() const { return m_inSendSyncCount; }
181
182     Identifier identifier() const;
183
184 #if PLATFORM(COCOA)
185     bool kill();
186 #endif
187
188 private:
189     Connection(Identifier, bool isServer, Client*, WTF::RunLoop& clientRunLoop);
190     void platformInitialize(Identifier);
191     void platformInvalidate();
192     
193     bool isValid() const { return m_client; }
194     
195     std::unique_ptr<MessageDecoder> waitForMessage(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, std::chrono::milliseconds timeout);
196     
197     std::unique_ptr<MessageDecoder> waitForSyncReply(uint64_t syncRequestID, std::chrono::milliseconds timeout, unsigned syncSendFlags);
198
199     // Called on the connection work queue.
200     void processIncomingMessage(std::unique_ptr<MessageDecoder>);
201     void processIncomingSyncReply(std::unique_ptr<MessageDecoder>);
202
203     void dispatchWorkQueueMessageReceiverMessage(WorkQueueMessageReceiver*, MessageDecoder*);
204
205     bool canSendOutgoingMessages() const;
206     bool platformCanSendOutgoingMessages() const;
207     void sendOutgoingMessages();
208     bool sendOutgoingMessage(std::unique_ptr<MessageEncoder>);
209     void connectionDidClose();
210     
211     // Called on the listener thread.
212     void dispatchConnectionDidClose();
213     void dispatchOneMessage();
214     void dispatchMessage(std::unique_ptr<MessageDecoder>);
215     void dispatchMessage(MessageDecoder&);
216     void dispatchSyncMessage(MessageDecoder&);
217     void dispatchDidReceiveInvalidMessage(const CString& messageReceiverNameString, const CString& messageNameString);
218     void didFailToSendSyncMessage();
219
220     // Can be called on any thread.
221     void enqueueIncomingMessage(std::unique_ptr<MessageDecoder>);
222
223     void willSendSyncMessage(unsigned syncSendFlags);
224     void didReceiveSyncReply(unsigned syncSendFlags);
225     
226     Client* m_client;
227     bool m_isServer;
228     std::atomic<uint64_t> m_syncRequestID;
229
230     bool m_onlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage;
231     bool m_shouldExitOnSyncMessageSendFailure;
232     DidCloseOnConnectionWorkQueueCallback m_didCloseOnConnectionWorkQueueCallback;
233
234     bool m_isConnected;
235     RefPtr<WorkQueue> m_connectionQueue;
236     WTF::RunLoop& m_clientRunLoop;
237
238     HashMap<StringReference, std::pair<RefPtr<WorkQueue>, RefPtr<WorkQueueMessageReceiver>>> m_workQueueMessageReceivers;
239
240     unsigned m_inSendSyncCount;
241     unsigned m_inDispatchMessageCount;
242     unsigned m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount;
243     bool m_didReceiveInvalidMessage;
244
245     // Incoming messages.
246     Mutex m_incomingMessagesLock;
247     Deque<std::unique_ptr<MessageDecoder>> m_incomingMessages;
248
249     // Outgoing messages.
250     Mutex m_outgoingMessagesLock;
251     Deque<std::unique_ptr<MessageEncoder>> m_outgoingMessages;
252     
253     std::condition_variable m_waitForMessageCondition;
254     std::mutex m_waitForMessageMutex;
255     bool m_messageWaitingInterruptedByClosedConnection;
256     HashMap<std::pair<std::pair<StringReference, StringReference>, uint64_t>, std::unique_ptr<MessageDecoder>> m_waitForMessageMap;
257
258     // Represents a sync request for which we're waiting on a reply.
259     struct PendingSyncReply {
260         // The request ID.
261         uint64_t syncRequestID;
262
263         // The reply decoder, will be null if there was an error processing the sync
264         // message on the other side.
265         std::unique_ptr<MessageDecoder> replyDecoder;
266
267         // Will be set to true once a reply has been received.
268         bool didReceiveReply;
269     
270         PendingSyncReply()
271             : syncRequestID(0)
272             , didReceiveReply(false)
273         {
274         }
275
276         explicit PendingSyncReply(uint64_t syncRequestID)
277             : syncRequestID(syncRequestID)
278             , didReceiveReply(0)
279         {
280         }
281     };
282
283     class SyncMessageState;
284     friend class SyncMessageState;
285     RefPtr<SyncMessageState> m_syncMessageState;
286
287     Mutex m_syncReplyStateMutex;
288     bool m_shouldWaitForSyncReplies;
289     Vector<PendingSyncReply> m_pendingSyncReplies;
290
291     class SecondaryThreadPendingSyncReply;
292     typedef HashMap<uint64_t, SecondaryThreadPendingSyncReply*> SecondaryThreadPendingSyncReplyMap;
293     SecondaryThreadPendingSyncReplyMap m_secondaryThreadPendingSyncReplyMap;
294
295 #if OS(DARWIN)
296     // Called on the connection queue.
297     void receiveSourceEventHandler();
298     void initializeDeadNameSource();
299
300     mach_port_t m_sendPort;
301     dispatch_source_t m_deadNameSource;
302
303     mach_port_t m_receivePort;
304     dispatch_source_t m_receivePortDataAvailableSource;
305
306 #if !PLATFORM(IOS)
307     void exceptionSourceEventHandler();
308
309     // If setShouldCloseConnectionOnMachExceptions has been called, this has
310     // the exception port that exceptions from the other end will be sent on.
311     mach_port_t m_exceptionPort;
312     dispatch_source_t m_exceptionPortDataAvailableSource;
313 #endif
314
315     XPCPtr<xpc_connection_t> m_xpcConnection;
316
317 #elif USE(UNIX_DOMAIN_SOCKETS)
318     // Called on the connection queue.
319     void readyReadHandler();
320     bool processMessage();
321
322     Vector<uint8_t> m_readBuffer;
323     size_t m_readBufferSize;
324     Vector<int> m_fileDescriptors;
325     size_t m_fileDescriptorsSize;
326     int m_socketDescriptor;
327 #endif
328 };
329
330 template<typename T> bool Connection::send(T&& message, uint64_t destinationID, unsigned messageSendFlags)
331 {
332     COMPILE_ASSERT(!T::isSync, AsyncMessageExpected);
333
334     auto encoder = std::make_unique<MessageEncoder>(T::receiverName(), T::name(), destinationID);
335     encoder->encode(message.arguments());
336     
337     return sendMessage(std::move(encoder), messageSendFlags);
338 }
339
340 template<typename T> bool Connection::sendSync(T&& message, typename T::Reply&& reply, uint64_t destinationID, std::chrono::milliseconds timeout, unsigned syncSendFlags)
341 {
342     COMPILE_ASSERT(T::isSync, SyncMessageExpected);
343
344     uint64_t syncRequestID = 0;
345     std::unique_ptr<MessageEncoder> encoder = createSyncMessageEncoder(T::receiverName(), T::name(), destinationID, syncRequestID);
346     
347     // Encode the rest of the input arguments.
348     encoder->encode(message.arguments());
349
350     // Now send the message and wait for a reply.
351     std::unique_ptr<MessageDecoder> replyDecoder = sendSyncMessage(syncRequestID, std::move(encoder), timeout, syncSendFlags);
352     if (!replyDecoder)
353         return false;
354
355     // Decode the reply.
356     return replyDecoder->decode(reply);
357 }
358
359 template<typename T> bool Connection::waitForAndDispatchImmediately(uint64_t destinationID, std::chrono::milliseconds timeout)
360 {
361     std::unique_ptr<MessageDecoder> decoder = waitForMessage(T::receiverName(), T::name(), destinationID, timeout);
362     if (!decoder)
363         return false;
364
365     ASSERT(decoder->destinationID() == destinationID);
366     m_client->didReceiveMessage(this, *decoder);
367     return true;
368 }
369
370 } // namespace IPC
371
372 #endif // Connection_h