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