[WK2] Use C++ lambdas in IPC::Connection
[WebKit-https.git] / Source / WebKit2 / Platform / IPC / mac / ConnectionMac.mm
1 /*
2  * Copyright (C) 2010 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 "Connection.h"
28
29 #include "DataReference.h"
30 #include "ImportanceAssertion.h"
31 #include "MachPort.h"
32 #include "MachUtilities.h"
33 #include <WebCore/AXObjectCache.h>
34 #include <mach/mach_error.h>
35 #include <mach/vm_map.h>
36 #include <wtf/RunLoop.h>
37 #include <wtf/spi/darwin/XPCSPI.h>
38
39 #if PLATFORM(IOS)
40 #include "ProcessAssertion.h"
41 #endif
42
43 #if __has_include(<HIServices/AccessibilityPriv.h>)
44 #include <HIServices/AccessibilityPriv.h>
45 #else
46 typedef enum {
47     AXSuspendStatusRunning = 0,
48     AXSuspendStatusSuspended,
49 } AXSuspendStatus;
50 #endif
51
52 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
53 extern "C" AXError _AXUIElementNotifyProcessSuspendStatus(AXSuspendStatus);
54 #endif
55
56 namespace IPC {
57
58 static const size_t inlineMessageMaxSize = 4096;
59
60 // Message flags.
61 enum {
62     MessageBodyIsOutOfLine = 1 << 0
63 };
64     
65 // ConnectionTerminationWatchdog does two things:
66 // 1) It sets a watchdog timer to kill the peered process.
67 // 2) On iOS, make the process runnable for the duration of the watchdog
68 //    to ensure it has a chance to terminate cleanly.
69 class ConnectionTerminationWatchdog {
70 public:
71     static void createConnectionTerminationWatchdog(OSObjectPtr<xpc_connection_t>& xpcConnection, double intervalInSeconds)
72     {
73         new ConnectionTerminationWatchdog(xpcConnection, intervalInSeconds);
74     }
75     
76 private:
77     ConnectionTerminationWatchdog(OSObjectPtr<xpc_connection_t>& xpcConnection, double intervalInSeconds)
78         : m_xpcConnection(xpcConnection)
79         , m_watchdogTimer(RunLoop::main(), this, &ConnectionTerminationWatchdog::watchdogTimerFired)
80 #if PLATFORM(IOS)
81         , m_assertion(std::make_unique<WebKit::ProcessAndUIAssertion>(xpc_connection_get_pid(m_xpcConnection.get()), WebKit::AssertionState::Background))
82 #endif
83     {
84         m_watchdogTimer.startOneShot(intervalInSeconds);
85     }
86     
87     void watchdogTimerFired()
88     {
89 #if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
90         xpc_connection_kill(m_xpcConnection.get(), SIGKILL);
91 #endif
92         delete this;
93     }
94
95     OSObjectPtr<xpc_connection_t> m_xpcConnection;
96     RunLoop::Timer<ConnectionTerminationWatchdog> m_watchdogTimer;
97 #if PLATFORM(IOS)
98     std::unique_ptr<WebKit::ProcessAndUIAssertion> m_assertion;
99 #endif
100 };
101     
102 void Connection::platformInvalidate()
103 {
104     if (!m_isConnected)
105         return;
106
107     m_isConnected = false;
108
109     ASSERT(m_sendPort);
110     ASSERT(m_receivePort);
111
112     // Unregister our ports.
113     dispatch_source_cancel(m_deadNameSource);
114     dispatch_release(m_deadNameSource);
115     m_deadNameSource = 0;
116     m_sendPort = MACH_PORT_NULL;
117
118     dispatch_source_cancel(m_receivePortDataAvailableSource);
119     dispatch_release(m_receivePortDataAvailableSource);
120     m_receivePortDataAvailableSource = 0;
121     m_receivePort = MACH_PORT_NULL;
122
123 #if !PLATFORM(IOS)
124     if (m_exceptionPort) {
125         dispatch_source_cancel(m_exceptionPortDataAvailableSource);
126         dispatch_release(m_exceptionPortDataAvailableSource);
127         m_exceptionPortDataAvailableSource = 0;
128         m_exceptionPort = MACH_PORT_NULL;
129     }
130 #endif
131
132     m_xpcConnection = nullptr;
133 }
134     
135 void Connection::terminateSoon(double intervalInSeconds)
136 {
137     if (m_xpcConnection)
138         ConnectionTerminationWatchdog::createConnectionTerminationWatchdog(m_xpcConnection, intervalInSeconds);
139 }
140     
141 void Connection::platformInitialize(Identifier identifier)
142 {
143 #if !PLATFORM(IOS)
144     m_exceptionPort = MACH_PORT_NULL;
145     m_exceptionPortDataAvailableSource = nullptr;
146 #endif
147
148     if (m_isServer) {
149         m_receivePort = identifier.port;
150         m_sendPort = MACH_PORT_NULL;
151     } else {
152         m_receivePort = MACH_PORT_NULL;
153         m_sendPort = identifier.port;
154     }
155
156     m_deadNameSource = nullptr;
157     m_receivePortDataAvailableSource = nullptr;
158
159     m_xpcConnection = identifier.xpcConnection;
160 }
161
162 template<typename Function>
163 static dispatch_source_t createDataAvailableSource(mach_port_t receivePort, WorkQueue& workQueue, Function&& function)
164 {
165     dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, receivePort, 0, workQueue.dispatchQueue());
166     dispatch_source_set_event_handler(source, function);
167
168     dispatch_source_set_cancel_handler(source, ^{
169         mach_port_mod_refs(mach_task_self(), receivePort, MACH_PORT_RIGHT_RECEIVE, -1);
170     });
171
172     return source;
173 }
174
175 bool Connection::open()
176 {
177     if (m_isServer) {
178         ASSERT(m_receivePort);
179         ASSERT(!m_sendPort);
180         
181     } else {
182         ASSERT(!m_receivePort);
183         ASSERT(m_sendPort);
184
185         // Create the receive port.
186         mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &m_receivePort);
187
188 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
189         mach_port_set_attributes(mach_task_self(), m_receivePort, MACH_PORT_DENAP_RECEIVER, (mach_port_info_t)0, 0);
190 #elif PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
191         mach_port_set_attributes(mach_task_self(), m_receivePort, MACH_PORT_IMPORTANCE_RECEIVER, (mach_port_info_t)0, 0);
192 #endif
193
194         m_isConnected = true;
195         
196         // Send the initialize message, which contains a send right for the server to use.
197         auto encoder = std::make_unique<MessageEncoder>("IPC", "InitializeConnection", 0);
198         encoder->encode(MachPort(m_receivePort, MACH_MSG_TYPE_MAKE_SEND));
199
200         sendMessage(WTF::move(encoder));
201
202         initializeDeadNameSource();
203     }
204
205     // Change the message queue length for the receive port.
206     setMachPortQueueLength(m_receivePort, MACH_PORT_QLIMIT_LARGE);
207
208     // Register the data available handler.
209     RefPtr<Connection> connection(this);
210     m_receivePortDataAvailableSource = createDataAvailableSource(m_receivePort, *m_connectionQueue, [connection] {
211         connection->receiveSourceEventHandler();
212     });
213
214 #if !PLATFORM(IOS)
215     // If we have an exception port, register the data available handler and send over the port to the other end.
216     if (m_exceptionPort) {
217         m_exceptionPortDataAvailableSource = createDataAvailableSource(m_exceptionPort, *m_connectionQueue, [connection] {
218             connection->exceptionSourceEventHandler();
219         });
220
221         auto encoder = std::make_unique<MessageEncoder>("IPC", "SetExceptionPort", 0);
222         encoder->encode(MachPort(m_exceptionPort, MACH_MSG_TYPE_MAKE_SEND));
223
224         sendMessage(WTF::move(encoder));
225     }
226 #endif
227
228     ref();
229     dispatch_async(m_connectionQueue->dispatchQueue(), ^{
230         dispatch_resume(m_receivePortDataAvailableSource);
231
232         if (m_deadNameSource)
233             dispatch_resume(m_deadNameSource);
234 #if !PLATFORM(IOS)
235         if (m_exceptionPortDataAvailableSource)
236             dispatch_resume(m_exceptionPortDataAvailableSource);
237 #endif
238
239         deref();
240     });
241
242     return true;
243 }
244
245 static inline size_t machMessageSize(size_t bodySize, size_t numberOfPortDescriptors = 0, size_t numberOfOOLMemoryDescriptors = 0)
246 {
247     size_t size = sizeof(mach_msg_header_t) + bodySize;
248     if (numberOfPortDescriptors || numberOfOOLMemoryDescriptors) {
249         size += sizeof(mach_msg_body_t);
250         if (numberOfPortDescriptors)
251             size += (numberOfPortDescriptors * sizeof(mach_msg_port_descriptor_t));
252         if (numberOfOOLMemoryDescriptors)
253             size += (numberOfOOLMemoryDescriptors * sizeof(mach_msg_ool_descriptor_t));
254     }
255     return round_msg(size);
256 }
257
258 bool Connection::platformCanSendOutgoingMessages() const
259 {
260     return true;
261 }
262
263 bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder)
264 {
265     Vector<Attachment> attachments = encoder->releaseAttachments();
266     
267     size_t numberOfPortDescriptors = 0;
268     size_t numberOfOOLMemoryDescriptors = 0;
269     for (size_t i = 0; i < attachments.size(); ++i) {
270         Attachment::Type type = attachments[i].type();
271         if (type == Attachment::MachPortType)
272             numberOfPortDescriptors++;
273     }
274     
275     size_t messageSize = machMessageSize(encoder->bufferSize(), numberOfPortDescriptors, numberOfOOLMemoryDescriptors);
276
277     bool messageBodyIsOOL = false;
278     if (messageSize > inlineMessageMaxSize) {
279         messageBodyIsOOL = true;
280
281         numberOfOOLMemoryDescriptors++;
282         messageSize = machMessageSize(0, numberOfPortDescriptors, numberOfOOLMemoryDescriptors);
283     }
284
285     char stackBuffer[inlineMessageMaxSize];
286     char* buffer = &stackBuffer[0];
287     if (messageSize > inlineMessageMaxSize)
288         buffer = (char*)mmap(0, messageSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
289
290     bool isComplex = (numberOfPortDescriptors + numberOfOOLMemoryDescriptors > 0);
291
292     mach_msg_header_t* header = reinterpret_cast<mach_msg_header_t*>(buffer);
293     header->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
294     header->msgh_size = messageSize;
295     header->msgh_remote_port = m_sendPort;
296     header->msgh_local_port = MACH_PORT_NULL;
297     header->msgh_id = 0;
298     if (messageBodyIsOOL)
299         header->msgh_id |= MessageBodyIsOutOfLine;
300
301     uint8_t* messageData;
302
303     if (isComplex) {
304         header->msgh_bits |= MACH_MSGH_BITS_COMPLEX;
305
306         mach_msg_body_t* body = reinterpret_cast<mach_msg_body_t*>(header + 1);
307         body->msgh_descriptor_count = numberOfPortDescriptors + numberOfOOLMemoryDescriptors;
308         uint8_t* descriptorData = reinterpret_cast<uint8_t*>(body + 1);
309
310         for (size_t i = 0; i < attachments.size(); ++i) {
311             Attachment attachment = attachments[i];
312
313             mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);
314             switch (attachment.type()) {
315             case Attachment::MachPortType:
316                 descriptor->port.name = attachment.port();
317                 descriptor->port.disposition = attachment.disposition();
318                 descriptor->port.type = MACH_MSG_PORT_DESCRIPTOR;            
319
320                 descriptorData += sizeof(mach_msg_port_descriptor_t);
321                 break;
322             default:
323                 ASSERT_NOT_REACHED();
324             }
325         }
326
327         if (messageBodyIsOOL) {
328             mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);
329
330             descriptor->out_of_line.address = encoder->buffer();
331             descriptor->out_of_line.size = encoder->bufferSize();
332             descriptor->out_of_line.copy = MACH_MSG_VIRTUAL_COPY;
333             descriptor->out_of_line.deallocate = false;
334             descriptor->out_of_line.type = MACH_MSG_OOL_DESCRIPTOR;
335
336             descriptorData += sizeof(mach_msg_ool_descriptor_t);
337         }
338
339         messageData = descriptorData;
340     } else
341         messageData = (uint8_t*)(header + 1);
342
343     // Copy the data if it is not being sent out-of-line.
344     if (!messageBodyIsOOL)
345         memcpy(messageData, encoder->buffer(), encoder->bufferSize());
346
347     ASSERT(m_sendPort);
348
349     // Send the message.
350     kern_return_t kr = mach_msg(header, MACH_SEND_MSG, messageSize, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
351     if (kr != KERN_SUCCESS) {
352         // FIXME: What should we do here?
353     }
354
355     if (buffer != &stackBuffer[0])
356         munmap(buffer, messageSize);
357
358     return true;
359 }
360
361 void Connection::initializeDeadNameSource()
362 {
363     m_deadNameSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_SEND, m_sendPort, 0, m_connectionQueue->dispatchQueue());
364
365     RefPtr<Connection> protectedThis(this);
366     dispatch_source_set_event_handler(m_deadNameSource, ^{
367         protectedThis->connectionDidClose();
368     });
369
370     mach_port_t sendPort = m_sendPort;
371     dispatch_source_set_cancel_handler(m_deadNameSource, ^{
372         // Release our send right.
373         mach_port_deallocate(mach_task_self(), sendPort);
374     });
375 }
376
377 static std::unique_ptr<MessageDecoder> createMessageDecoder(mach_msg_header_t* header)
378 {
379     if (!(header->msgh_bits & MACH_MSGH_BITS_COMPLEX)) {
380         // We have a simple message.
381         uint8_t* body = reinterpret_cast<uint8_t*>(header + 1);
382         size_t bodySize = header->msgh_size - sizeof(mach_msg_header_t);
383
384         return std::make_unique<MessageDecoder>(DataReference(body, bodySize), Vector<Attachment>());
385     }
386
387     bool messageBodyIsOOL = header->msgh_id & MessageBodyIsOutOfLine;
388
389     mach_msg_body_t* body = reinterpret_cast<mach_msg_body_t*>(header + 1);
390     mach_msg_size_t numDescriptors = body->msgh_descriptor_count;
391     ASSERT(numDescriptors);
392
393     uint8_t* descriptorData = reinterpret_cast<uint8_t*>(body + 1);
394
395     // If the message body was sent out-of-line, don't treat the last descriptor
396     // as an attachment, since it is really the message body.
397     if (messageBodyIsOOL)
398         --numDescriptors;
399
400     // Build attachment list
401     Vector<Attachment> attachments(numDescriptors);
402
403     for (mach_msg_size_t i = 0; i < numDescriptors; ++i) {
404         mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);
405
406         switch (descriptor->type.type) {
407         case MACH_MSG_PORT_DESCRIPTOR:
408             attachments[numDescriptors - i - 1] = Attachment(descriptor->port.name, descriptor->port.disposition);
409             descriptorData += sizeof(mach_msg_port_descriptor_t);
410             break;
411         default:
412             ASSERT(false && "Unhandled descriptor type");
413         }
414     }
415
416     if (messageBodyIsOOL) {
417         mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);
418         ASSERT(descriptor->type.type == MACH_MSG_OOL_DESCRIPTOR);
419
420         uint8_t* messageBody = static_cast<uint8_t*>(descriptor->out_of_line.address);
421         size_t messageBodySize = descriptor->out_of_line.size;
422
423         auto decoder = std::make_unique<MessageDecoder>(DataReference(messageBody, messageBodySize), WTF::move(attachments));
424
425         vm_deallocate(mach_task_self(), reinterpret_cast<vm_address_t>(descriptor->out_of_line.address), descriptor->out_of_line.size);
426
427         return decoder;
428     }
429
430     uint8_t* messageBody = descriptorData;
431     size_t messageBodySize = header->msgh_size - (descriptorData - reinterpret_cast<uint8_t*>(header));
432
433     return std::make_unique<MessageDecoder>(DataReference(messageBody, messageBodySize), attachments);
434 }
435
436 // The receive buffer size should always include the maximum trailer size.
437 static const size_t receiveBufferSize = inlineMessageMaxSize + MAX_TRAILER_SIZE;
438 typedef Vector<char, receiveBufferSize> ReceiveBuffer;
439
440 static mach_msg_header_t* readFromMachPort(mach_port_t machPort, ReceiveBuffer& buffer)
441 {
442     buffer.resize(receiveBufferSize);
443
444     mach_msg_header_t* header = reinterpret_cast<mach_msg_header_t*>(buffer.data());
445     kern_return_t kr = mach_msg(header, MACH_RCV_MSG | MACH_RCV_LARGE | MACH_RCV_TIMEOUT, 0, buffer.size(), machPort, 0, MACH_PORT_NULL);
446     if (kr == MACH_RCV_TIMED_OUT)
447         return 0;
448
449     if (kr == MACH_RCV_TOO_LARGE) {
450         // The message was too large, resize the buffer and try again.
451         buffer.resize(header->msgh_size + MAX_TRAILER_SIZE);
452         header = reinterpret_cast<mach_msg_header_t*>(buffer.data());
453         
454         kr = mach_msg(header, MACH_RCV_MSG | MACH_RCV_LARGE | MACH_RCV_TIMEOUT, 0, buffer.size(), machPort, 0, MACH_PORT_NULL);
455         ASSERT(kr != MACH_RCV_TOO_LARGE);
456     }
457
458     if (kr != MACH_MSG_SUCCESS) {
459         ASSERT_NOT_REACHED();
460         return 0;
461     }
462
463     return header;
464 }
465
466 void Connection::receiveSourceEventHandler()
467 {
468     ReceiveBuffer buffer;
469
470     mach_msg_header_t* header = readFromMachPort(m_receivePort, buffer);
471     if (!header)
472         return;
473
474     std::unique_ptr<MessageDecoder> decoder = createMessageDecoder(header);
475     ASSERT(decoder);
476
477 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
478     decoder->setImportanceAssertion(std::make_unique<ImportanceAssertion>(header));
479 #endif
480
481     if (decoder->messageReceiverName() == "IPC" && decoder->messageName() == "InitializeConnection") {
482         ASSERT(m_isServer);
483         ASSERT(!m_isConnected);
484         ASSERT(!m_sendPort);
485
486         MachPort port;
487         if (!decoder->decode(port)) {
488             // FIXME: Disconnect.
489             return;
490         }
491
492         m_sendPort = port.port();
493         
494         if (m_sendPort) {
495             initializeDeadNameSource();
496             dispatch_resume(m_deadNameSource);
497         }
498
499         m_isConnected = true;
500
501         // Send any pending outgoing messages.
502         sendOutgoingMessages();
503         
504         return;
505     }
506
507 #if !PLATFORM(IOS)
508     if (decoder->messageReceiverName() == "IPC" && decoder->messageName() == "SetExceptionPort") {
509         if (m_isServer) {
510             // Server connections aren't supposed to have their exception ports overriden. Treat this as an invalid message.
511             RefPtr<Connection> protectedThis(this);
512             CString messageReceiverNameString = decoder->messageReceiverName().toString();
513             CString messageNameString = decoder->messageName().toString();
514             m_clientRunLoop.dispatch([protectedThis, messageReceiverNameString, messageNameString] {
515                 protectedThis->dispatchDidReceiveInvalidMessage(messageReceiverNameString, messageNameString);
516             });
517             return;
518         }
519         MachPort exceptionPort;
520         if (!decoder->decode(exceptionPort))
521             return;
522
523         setMachExceptionPort(exceptionPort.port());
524         return;
525     }
526 #endif
527
528     processIncomingMessage(WTF::move(decoder));
529 }    
530
531 #if !PLATFORM(IOS)
532 void Connection::exceptionSourceEventHandler()
533 {
534     ReceiveBuffer buffer;
535
536     mach_msg_header_t* header = readFromMachPort(m_exceptionPort, buffer);
537     if (!header)
538         return;
539
540     // We've read the exception message. Now send it on to the real exception port.
541
542     // The remote port should have a send once right.
543     ASSERT(MACH_MSGH_BITS_REMOTE(header->msgh_bits) == MACH_MSG_TYPE_MOVE_SEND_ONCE);
544
545     // Now get the real exception port.
546     mach_port_t exceptionPort = machExceptionPort();
547
548     // First, get the complex bit from the source message.
549     mach_msg_bits_t messageBits = header->msgh_bits & MACH_MSGH_BITS_COMPLEX;
550     messageBits |= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MOVE_SEND_ONCE);
551
552     header->msgh_bits = messageBits;
553     header->msgh_local_port = header->msgh_remote_port;
554     header->msgh_remote_port = exceptionPort;
555
556     // Now send along the message.
557     kern_return_t kr = mach_msg(header, MACH_SEND_MSG, header->msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
558     if (kr != KERN_SUCCESS)
559         LOG_ERROR("Failed to send message to real exception port. %s (%x)", mach_error_string(kr), kr);
560
561     connectionDidClose();
562 }
563
564 void Connection::setShouldCloseConnectionOnMachExceptions()
565 {
566     ASSERT(m_exceptionPort == MACH_PORT_NULL);
567
568     if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &m_exceptionPort) != KERN_SUCCESS)
569         ASSERT_NOT_REACHED();
570
571     if (mach_port_insert_right(mach_task_self(), m_exceptionPort, m_exceptionPort, MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS)
572         ASSERT_NOT_REACHED();
573 }
574 #endif
575
576 IPC::Connection::Identifier Connection::identifier() const
577 {
578     return Identifier(m_isServer ? m_receivePort : m_sendPort, m_xpcConnection);
579 }
580
581 bool Connection::getAuditToken(audit_token_t& auditToken)
582 {
583     if (!m_xpcConnection)
584         return false;
585     
586     xpc_connection_get_audit_token(m_xpcConnection.get(), &auditToken);
587     return true;
588 }
589
590 bool Connection::kill()
591 {
592 #if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
593     if (m_xpcConnection) {
594         xpc_connection_kill(m_xpcConnection.get(), SIGKILL);
595         return true;
596     }
597 #endif
598
599     return false;
600 }
601     
602 void Connection::willSendSyncMessage(unsigned flags)
603 {
604 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
605     if ((flags & InformPlatformProcessWillSuspend) && WebCore::AXObjectCache::accessibilityEnabled())
606         _AXUIElementNotifyProcessSuspendStatus(AXSuspendStatusSuspended);
607 #endif
608 }
609
610 void Connection::didReceiveSyncReply(unsigned flags)
611 {
612 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
613     if ((flags & InformPlatformProcessWillSuspend) && WebCore::AXObjectCache::accessibilityEnabled())
614         _AXUIElementNotifyProcessSuspendStatus(AXSuspendStatusRunning);
615 #endif
616 }    
617     
618 } // namespace IPC