935ae9c0645dfcd6dcd081db47e7f2e1230afe35
[WebKit-https.git] / Source / WebKit2 / Platform / CoreIPC / 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 "ArgumentDecoder.h"
32 #include "ArgumentEncoder.h"
33 #include "Arguments.h"
34 #include "MessageID.h"
35 #include "WorkQueue.h"
36 #include <wtf/HashMap.h>
37 #include <wtf/PassRefPtr.h>
38 #include <wtf/OwnPtr.h>
39 #include <wtf/Threading.h>
40
41 #if PLATFORM(MAC)
42 #include <mach/mach_port.h>
43 #elif PLATFORM(WIN)
44 #include <string>
45 #elif PLATFORM(QT)
46 class QSocketNotifier;
47 #include "PlatformProcessIdentifier.h"
48 #endif
49
50 class RunLoop;
51
52 namespace CoreIPC {
53
54 class MessageID;
55     
56 enum SyncReplyMode {
57     AutomaticReply,
58     ManualReply
59 };
60
61 enum MessageSendFlags {
62     // Whether this message should be dispatched when waiting for a sync reply.
63     // This is the default for synchronous messages.
64     DispatchMessageEvenWhenWaitingForSyncReply = 1 << 0,
65 };
66
67 #define MESSAGE_CHECK_BASE(assertion, connection) do \
68     if (!(assertion)) { \
69         ASSERT(assertion); \
70         (connection)->markCurrentlyDispatchedMessageAsInvalid(); \
71         return; \
72     } \
73 while (0)
74
75 class Connection : public ThreadSafeShared<Connection> {
76 public:
77     class MessageReceiver {
78     protected:
79         virtual ~MessageReceiver() { }
80
81     public:
82         virtual void didReceiveMessage(Connection*, MessageID, ArgumentDecoder*) = 0;
83         virtual SyncReplyMode didReceiveSyncMessage(Connection*, MessageID, ArgumentDecoder*, ArgumentEncoder*) { ASSERT_NOT_REACHED(); return AutomaticReply; }
84     };
85     
86     class Client : public MessageReceiver {
87     protected:
88         virtual ~Client() { }
89
90     public:
91         virtual void didClose(Connection*) = 0;
92         virtual void didReceiveInvalidMessage(Connection*, MessageID) = 0;
93         virtual void didFailToSendSyncMessage(Connection*) { }
94     };
95
96 #if PLATFORM(MAC)
97     typedef mach_port_t Identifier;
98 #elif PLATFORM(WIN)
99     typedef HANDLE Identifier;
100     static bool createServerAndClientIdentifiers(Identifier& serverIdentifier, Identifier& clientIdentifier);
101 #elif PLATFORM(QT)
102     typedef int Identifier;
103 #elif PLATFORM(GTK)
104     typedef int Identifier;
105 #endif
106
107     static PassRefPtr<Connection> createServerConnection(Identifier, Client*, RunLoop* clientRunLoop);
108     static PassRefPtr<Connection> createClientConnection(Identifier, Client*, RunLoop* clientRunLoop);
109     ~Connection();
110
111 #if PLATFORM(MAC)
112     void setShouldCloseConnectionOnMachExceptions();
113 #elif PLATFORM(QT)
114     void setShouldCloseConnectionOnProcessTermination(WebKit::PlatformProcessIdentifier);
115 #endif
116
117     // The set callback will be called on the connection work queue when the connection is closed, 
118     // before didCall is called on the client thread. Must be called before the connection is opened.
119     // In the future we might want a more generic way to handle sync or async messages directly
120     // on the work queue, for example if we want to handle them on some other thread we could avoid
121     // handling the message on the client thread first.
122     typedef void (*DidCloseOnConnectionWorkQueueCallback)(WorkQueue&, Connection*);
123     void setDidCloseOnConnectionWorkQueueCallback(DidCloseOnConnectionWorkQueueCallback callback);
124                                                 
125     bool open();
126     void invalidate();
127     void markCurrentlyDispatchedMessageAsInvalid();
128
129     static const unsigned long long NoTimeout = 10000000000ULL;
130
131     template<typename T> bool send(const T& message, uint64_t destinationID, unsigned messageSendFlags = 0);
132     template<typename T> bool sendSync(const T& message, const typename T::Reply& reply, uint64_t destinationID, double timeout = NoTimeout);
133     template<typename T> bool waitForAndDispatchImmediately(uint64_t destinationID, double timeout);
134
135     PassOwnPtr<ArgumentEncoder> createSyncMessageArgumentEncoder(uint64_t destinationID, uint64_t& syncRequestID);
136     bool sendMessage(MessageID, PassOwnPtr<ArgumentEncoder>, unsigned messageSendFlags = 0);
137     bool sendSyncReply(PassOwnPtr<ArgumentEncoder>);
138
139     // FIXME: These variants of senc, sendSync and waitFor are all deprecated.
140     // All clients should move to the overloads that take a message type.
141     template<typename E, typename T> bool deprecatedSend(E messageID, uint64_t destinationID, const T& arguments);
142     template<typename E, typename T, typename U> bool deprecatedSendSync(E messageID, uint64_t destinationID, const T& arguments, const U& reply, double timeout = NoTimeout);
143     template<typename E> PassOwnPtr<ArgumentDecoder> deprecatedWaitFor(E messageID, uint64_t destinationID, double timeout);
144     
145 private:
146     template<typename T> class Message {
147     public:
148         Message()
149             : m_arguments(0)
150         {
151         }
152
153         Message(MessageID messageID, PassOwnPtr<T> arguments)
154             : m_messageID(messageID)
155             , m_arguments(arguments.leakPtr())
156         {
157         }
158         
159         MessageID messageID() const { return m_messageID; }
160         T* arguments() const { return m_arguments; }
161         
162         PassOwnPtr<T> releaseArguments()
163         {
164             T* arguments = m_arguments;
165             m_arguments = 0;
166
167             return arguments;
168         }
169         
170     private:
171         MessageID m_messageID;
172         T* m_arguments;
173     };
174
175 public:
176     typedef Message<ArgumentEncoder> OutgoingMessage;
177
178 private:
179     Connection(Identifier, bool isServer, Client*, RunLoop* clientRunLoop);
180     void platformInitialize(Identifier);
181     void platformInvalidate();
182     
183     bool isValid() const { return m_client; }
184     
185     PassOwnPtr<ArgumentDecoder> waitForMessage(MessageID, uint64_t destinationID, double timeout);
186     
187     PassOwnPtr<ArgumentDecoder> sendSyncMessage(MessageID, uint64_t syncRequestID, PassOwnPtr<ArgumentEncoder>, double timeout);
188     PassOwnPtr<ArgumentDecoder> waitForSyncReply(uint64_t syncRequestID, double timeout);
189
190     // Called on the connection work queue.
191     void processIncomingMessage(MessageID, PassOwnPtr<ArgumentDecoder>);
192     bool canSendOutgoingMessages() const;
193     bool platformCanSendOutgoingMessages() const;
194     void sendOutgoingMessages();
195     bool sendOutgoingMessage(MessageID, PassOwnPtr<ArgumentEncoder>);
196     void connectionDidClose();
197     
198     typedef Message<ArgumentDecoder> IncomingMessage;
199
200     // Called on the listener thread.
201     void dispatchConnectionDidClose();
202     void dispatchMessage(IncomingMessage&);
203     void dispatchMessages();
204     void dispatchSyncMessage(MessageID, ArgumentDecoder*);
205                              
206     Client* m_client;
207     bool m_isServer;
208     uint64_t m_syncRequestID;
209
210     DidCloseOnConnectionWorkQueueCallback m_didCloseOnConnectionWorkQueueCallback;
211
212     bool m_isConnected;
213     WorkQueue m_connectionQueue;
214     RunLoop* m_clientRunLoop;
215
216     uint32_t m_inDispatchMessageCount;
217     bool m_didReceiveInvalidMessage;
218
219     // Incoming messages.
220     Mutex m_incomingMessagesLock;
221     Vector<IncomingMessage> m_incomingMessages;
222
223     // Outgoing messages.
224     Mutex m_outgoingMessagesLock;
225     Deque<OutgoingMessage> m_outgoingMessages;
226     
227     ThreadCondition m_waitForMessageCondition;
228     Mutex m_waitForMessageMutex;
229     HashMap<std::pair<unsigned, uint64_t>, ArgumentDecoder*> m_waitForMessageMap;
230
231     // Represents a sync request for which we're waiting on a reply.
232     struct PendingSyncReply {
233         // The request ID.
234         uint64_t syncRequestID;
235
236         // The reply decoder, will be null if there was an error processing the sync
237         // message on the other side.
238         ArgumentDecoder* replyDecoder;
239
240         // Will be set to true once a reply has been received or an error occurred.
241         bool didReceiveReply;
242     
243         PendingSyncReply()
244             : syncRequestID(0)
245             , replyDecoder(0)
246             , didReceiveReply(false)
247         {
248         }
249
250         explicit PendingSyncReply(uint64_t syncRequestID)
251             : syncRequestID(syncRequestID)
252             , replyDecoder(0)
253             , didReceiveReply(0)
254         {
255         }
256
257         PassOwnPtr<ArgumentDecoder> releaseReplyDecoder()
258         {
259             OwnPtr<ArgumentDecoder> reply = adoptPtr(replyDecoder);
260             replyDecoder = 0;
261             
262             return reply.release();
263         }
264     };
265     
266     class SyncMessageState;
267     friend class SyncMessageState;
268     RefPtr<SyncMessageState> m_syncMessageState;
269
270     Mutex m_syncReplyStateMutex;
271     bool m_shouldWaitForSyncReplies;
272     Vector<PendingSyncReply> m_pendingSyncReplies;
273     Vector<IncomingMessage> m_syncMessagesReceivedWhileWaitingForSyncReply;
274
275 #if PLATFORM(MAC)
276     // Called on the connection queue.
277     void receiveSourceEventHandler();
278     void initializeDeadNameSource();
279     void exceptionSourceEventHandler();
280
281     mach_port_t m_sendPort;
282     mach_port_t m_receivePort;
283
284     // If setShouldCloseConnectionOnMachExceptions has been called, this has
285     // the exception port that exceptions from the other end will be sent on.
286     mach_port_t m_exceptionPort;
287
288 #elif PLATFORM(WIN)
289     // Called on the connection queue.
290     void readEventHandler();
291     void writeEventHandler();
292
293     Vector<uint8_t> m_readBuffer;
294     OVERLAPPED m_readState;
295     OwnPtr<ArgumentEncoder> m_pendingWriteArguments;
296     OVERLAPPED m_writeState;
297     HANDLE m_connectionPipe;
298 #elif PLATFORM(QT)
299     // Called on the connection queue.
300     void readyReadHandler();
301
302     Vector<uint8_t> m_readBuffer;
303     size_t m_currentMessageSize;
304     QSocketNotifier* m_socketNotifier;
305     int m_socketDescriptor;
306 #elif PLATFORM(GTK)
307     void readEventHandler();
308     void processCompletedMessage();
309     bool messageProcessingCompleted() { return !m_currentMessageSize; }
310
311     int m_socket;
312     Vector<uint8_t> m_readBuffer;
313     size_t m_currentMessageSize;
314     size_t m_pendingBytes;
315 #endif
316 };
317
318 template<typename T> bool Connection::send(const T& message, uint64_t destinationID, unsigned messageSendFlags)
319 {
320     OwnPtr<ArgumentEncoder> argumentEncoder = ArgumentEncoder::create(destinationID);
321     argumentEncoder->encode(message);
322     
323     return sendMessage(MessageID(T::messageID), argumentEncoder.release(), messageSendFlags);
324 }
325
326 template<typename T> bool Connection::sendSync(const T& message, const typename T::Reply& reply, uint64_t destinationID, double timeout)
327 {
328     uint64_t syncRequestID = 0;
329     OwnPtr<ArgumentEncoder> argumentEncoder = createSyncMessageArgumentEncoder(destinationID, syncRequestID);
330     
331     // Encode the rest of the input arguments.
332     argumentEncoder->encode(message);
333
334     // Now send the message and wait for a reply.
335     OwnPtr<ArgumentDecoder> replyDecoder = sendSyncMessage(MessageID(T::messageID, MessageID::SyncMessage), syncRequestID, argumentEncoder.release(), timeout);
336     if (!replyDecoder)
337         return false;
338
339     // Decode the reply.
340     return replyDecoder->decode(const_cast<typename T::Reply&>(reply));
341 }
342
343 template<typename T> bool Connection::waitForAndDispatchImmediately(uint64_t destinationID, double timeout)
344 {
345     OwnPtr<ArgumentDecoder> decoder = waitForMessage(MessageID(T::messageID), destinationID, timeout);
346     if (!decoder)
347         return false;
348
349     ASSERT(decoder->destinationID() == destinationID);
350     m_client->didReceiveMessage(this, MessageID(T::messageID), decoder.get());
351     return true;
352 }
353
354 // These three member functions are all deprecated.
355
356 template<typename E, typename T, typename U>
357 inline bool Connection::deprecatedSendSync(E messageID, uint64_t destinationID, const T& arguments, const U& reply, double timeout)
358 {
359     uint64_t syncRequestID = 0;
360     OwnPtr<ArgumentEncoder> argumentEncoder = createSyncMessageArgumentEncoder(destinationID, syncRequestID);
361
362     // Encode the input arguments.
363     argumentEncoder->encode(arguments);
364     
365     // Now send the message and wait for a reply.
366     OwnPtr<ArgumentDecoder> replyDecoder = sendSyncMessage(MessageID(messageID, MessageID::SyncMessage), syncRequestID, argumentEncoder.release(), timeout);
367     if (!replyDecoder)
368         return false;
369     
370     // Decode the reply.
371     return replyDecoder->decode(const_cast<U&>(reply));
372 }
373
374 template<typename E, typename T>
375 bool Connection::deprecatedSend(E messageID, uint64_t destinationID, const T& arguments)
376 {
377     OwnPtr<ArgumentEncoder> argumentEncoder = ArgumentEncoder::create(destinationID);
378     argumentEncoder->encode(arguments);
379
380     return sendMessage(MessageID(messageID), argumentEncoder.release());
381 }
382
383 template<typename E> inline PassOwnPtr<ArgumentDecoder> Connection::deprecatedWaitFor(E messageID, uint64_t destinationID, double timeout)
384 {
385     return waitForMessage(MessageID(messageID), destinationID, timeout);
386 }
387
388 } // namespace CoreIPC
389
390 #endif // Connection_h