Only do the Connection::setShouldCloseConnectionOnMachExceptions() hack where necessary
[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(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED <= 101000
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(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED <= 101000
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(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED <= 101000
214     if (m_exceptionPort) {
215         m_exceptionPortDataAvailableSource = createDataAvailableSource(m_exceptionPort, m_connectionQueue, [connection] {
216             connection->exceptionSourceEventHandler();
217         });
218
219         auto encoder = std::make_unique<MessageEncoder>("IPC", "SetExceptionPort", 0);
220         encoder->encode(MachPort(m_exceptionPort, MACH_MSG_TYPE_MAKE_SEND));
221
222         sendMessage(WTF::move(encoder));
223     }
224 #endif
225
226     ref();
227     dispatch_async(m_connectionQueue->dispatchQueue(), ^{
228         dispatch_resume(m_receivePortDataAvailableSource);
229
230         if (m_deadNameSource)
231             dispatch_resume(m_deadNameSource);
232 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED <= 101000
233         if (m_exceptionPortDataAvailableSource)
234             dispatch_resume(m_exceptionPortDataAvailableSource);
235 #endif
236
237         deref();
238     });
239
240     return true;
241 }
242
243 static inline size_t machMessageSize(size_t bodySize, size_t numberOfPortDescriptors = 0, size_t numberOfOOLMemoryDescriptors = 0)
244 {
245     size_t size = sizeof(mach_msg_header_t) + bodySize;
246     if (numberOfPortDescriptors || numberOfOOLMemoryDescriptors) {
247         size += sizeof(mach_msg_body_t);
248         if (numberOfPortDescriptors)
249             size += (numberOfPortDescriptors * sizeof(mach_msg_port_descriptor_t));
250         if (numberOfOOLMemoryDescriptors)
251             size += (numberOfOOLMemoryDescriptors * sizeof(mach_msg_ool_descriptor_t));
252     }
253     return round_msg(size);
254 }
255
256 bool Connection::platformCanSendOutgoingMessages() const
257 {
258     return true;
259 }
260
261 bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder)
262 {
263     Vector<Attachment> attachments = encoder->releaseAttachments();
264     
265     size_t numberOfPortDescriptors = 0;
266     size_t numberOfOOLMemoryDescriptors = 0;
267     for (size_t i = 0; i < attachments.size(); ++i) {
268         Attachment::Type type = attachments[i].type();
269         if (type == Attachment::MachPortType)
270             numberOfPortDescriptors++;
271     }
272     
273     size_t messageSize = machMessageSize(encoder->bufferSize(), numberOfPortDescriptors, numberOfOOLMemoryDescriptors);
274
275     bool messageBodyIsOOL = false;
276     if (messageSize > inlineMessageMaxSize) {
277         messageBodyIsOOL = true;
278
279         numberOfOOLMemoryDescriptors++;
280         messageSize = machMessageSize(0, numberOfPortDescriptors, numberOfOOLMemoryDescriptors);
281     }
282
283     char stackBuffer[inlineMessageMaxSize];
284     char* buffer = &stackBuffer[0];
285     if (messageSize > inlineMessageMaxSize) {
286         buffer = (char*)mmap(0, messageSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
287         if (buffer == MAP_FAILED)
288             return false;
289     }
290
291     bool isComplex = (numberOfPortDescriptors + numberOfOOLMemoryDescriptors > 0);
292
293     mach_msg_header_t* header = reinterpret_cast<mach_msg_header_t*>(buffer);
294     header->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
295     header->msgh_size = messageSize;
296     header->msgh_remote_port = m_sendPort;
297     header->msgh_local_port = MACH_PORT_NULL;
298     header->msgh_id = 0;
299     if (messageBodyIsOOL)
300         header->msgh_id |= MessageBodyIsOutOfLine;
301
302     uint8_t* messageData;
303
304     if (isComplex) {
305         header->msgh_bits |= MACH_MSGH_BITS_COMPLEX;
306
307         mach_msg_body_t* body = reinterpret_cast<mach_msg_body_t*>(header + 1);
308         body->msgh_descriptor_count = numberOfPortDescriptors + numberOfOOLMemoryDescriptors;
309         uint8_t* descriptorData = reinterpret_cast<uint8_t*>(body + 1);
310
311         for (size_t i = 0; i < attachments.size(); ++i) {
312             Attachment attachment = attachments[i];
313
314             mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);
315             switch (attachment.type()) {
316             case Attachment::MachPortType:
317                 descriptor->port.name = attachment.port();
318                 descriptor->port.disposition = attachment.disposition();
319                 descriptor->port.type = MACH_MSG_PORT_DESCRIPTOR;            
320
321                 descriptorData += sizeof(mach_msg_port_descriptor_t);
322                 break;
323             default:
324                 ASSERT_NOT_REACHED();
325             }
326         }
327
328         if (messageBodyIsOOL) {
329             mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);
330
331             descriptor->out_of_line.address = encoder->buffer();
332             descriptor->out_of_line.size = encoder->bufferSize();
333             descriptor->out_of_line.copy = MACH_MSG_VIRTUAL_COPY;
334             descriptor->out_of_line.deallocate = false;
335             descriptor->out_of_line.type = MACH_MSG_OOL_DESCRIPTOR;
336
337             descriptorData += sizeof(mach_msg_ool_descriptor_t);
338         }
339
340         messageData = descriptorData;
341     } else
342         messageData = (uint8_t*)(header + 1);
343
344     // Copy the data if it is not being sent out-of-line.
345     if (!messageBodyIsOOL)
346         memcpy(messageData, encoder->buffer(), encoder->bufferSize());
347
348     ASSERT(m_sendPort);
349
350     // Send the message.
351     kern_return_t kr = mach_msg(header, MACH_SEND_MSG, messageSize, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
352     if (kr != KERN_SUCCESS) {
353         // FIXME: What should we do here?
354     }
355
356     if (buffer != &stackBuffer[0])
357         munmap(buffer, messageSize);
358
359     return true;
360 }
361
362 void Connection::initializeDeadNameSource()
363 {
364     m_deadNameSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_SEND, m_sendPort, 0, m_connectionQueue->dispatchQueue());
365
366     RefPtr<Connection> connection(this);
367     dispatch_source_set_event_handler(m_deadNameSource, [connection] {
368         connection->connectionDidClose();
369     });
370
371     mach_port_t sendPort = m_sendPort;
372     dispatch_source_set_cancel_handler(m_deadNameSource, ^{
373         // Release our send right.
374         mach_port_deallocate(mach_task_self(), sendPort);
375     });
376 }
377
378 static std::unique_ptr<MessageDecoder> createMessageDecoder(mach_msg_header_t* header)
379 {
380     if (!(header->msgh_bits & MACH_MSGH_BITS_COMPLEX)) {
381         // We have a simple message.
382         uint8_t* body = reinterpret_cast<uint8_t*>(header + 1);
383         size_t bodySize = header->msgh_size - sizeof(mach_msg_header_t);
384
385         return std::make_unique<MessageDecoder>(DataReference(body, bodySize), Vector<Attachment>());
386     }
387
388     bool messageBodyIsOOL = header->msgh_id & MessageBodyIsOutOfLine;
389
390     mach_msg_body_t* body = reinterpret_cast<mach_msg_body_t*>(header + 1);
391     mach_msg_size_t numDescriptors = body->msgh_descriptor_count;
392     ASSERT(numDescriptors);
393
394     uint8_t* descriptorData = reinterpret_cast<uint8_t*>(body + 1);
395
396     // If the message body was sent out-of-line, don't treat the last descriptor
397     // as an attachment, since it is really the message body.
398     if (messageBodyIsOOL)
399         --numDescriptors;
400
401     // Build attachment list
402     Vector<Attachment> attachments(numDescriptors);
403
404     for (mach_msg_size_t i = 0; i < numDescriptors; ++i) {
405         mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);
406
407         switch (descriptor->type.type) {
408         case MACH_MSG_PORT_DESCRIPTOR:
409             attachments[numDescriptors - i - 1] = Attachment(descriptor->port.name, descriptor->port.disposition);
410             descriptorData += sizeof(mach_msg_port_descriptor_t);
411             break;
412         default:
413             ASSERT(false && "Unhandled descriptor type");
414         }
415     }
416
417     if (messageBodyIsOOL) {
418         mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);
419         ASSERT(descriptor->type.type == MACH_MSG_OOL_DESCRIPTOR);
420
421         uint8_t* messageBody = static_cast<uint8_t*>(descriptor->out_of_line.address);
422         size_t messageBodySize = descriptor->out_of_line.size;
423
424         auto decoder = std::make_unique<MessageDecoder>(DataReference(messageBody, messageBodySize), WTF::move(attachments));
425
426         vm_deallocate(mach_task_self(), reinterpret_cast<vm_address_t>(descriptor->out_of_line.address), descriptor->out_of_line.size);
427
428         return decoder;
429     }
430
431     uint8_t* messageBody = descriptorData;
432     size_t messageBodySize = header->msgh_size - (descriptorData - reinterpret_cast<uint8_t*>(header));
433
434     return std::make_unique<MessageDecoder>(DataReference(messageBody, messageBodySize), attachments);
435 }
436
437 // The receive buffer size should always include the maximum trailer size.
438 static const size_t receiveBufferSize = inlineMessageMaxSize + MAX_TRAILER_SIZE;
439 typedef Vector<char, receiveBufferSize> ReceiveBuffer;
440
441 static mach_msg_header_t* readFromMachPort(mach_port_t machPort, ReceiveBuffer& buffer)
442 {
443     buffer.resize(receiveBufferSize);
444
445     mach_msg_header_t* header = reinterpret_cast<mach_msg_header_t*>(buffer.data());
446     kern_return_t kr = mach_msg(header, MACH_RCV_MSG | MACH_RCV_LARGE | MACH_RCV_TIMEOUT, 0, buffer.size(), machPort, 0, MACH_PORT_NULL);
447     if (kr == MACH_RCV_TIMED_OUT)
448         return 0;
449
450     if (kr == MACH_RCV_TOO_LARGE) {
451         // The message was too large, resize the buffer and try again.
452         buffer.resize(header->msgh_size + MAX_TRAILER_SIZE);
453         header = reinterpret_cast<mach_msg_header_t*>(buffer.data());
454         
455         kr = mach_msg(header, MACH_RCV_MSG | MACH_RCV_LARGE | MACH_RCV_TIMEOUT, 0, buffer.size(), machPort, 0, MACH_PORT_NULL);
456         ASSERT(kr != MACH_RCV_TOO_LARGE);
457     }
458
459     if (kr != MACH_MSG_SUCCESS) {
460         ASSERT_NOT_REACHED();
461         return 0;
462     }
463
464     return header;
465 }
466
467 void Connection::receiveSourceEventHandler()
468 {
469     ReceiveBuffer buffer;
470
471     mach_msg_header_t* header = readFromMachPort(m_receivePort, buffer);
472     if (!header)
473         return;
474
475     std::unique_ptr<MessageDecoder> decoder = createMessageDecoder(header);
476     ASSERT(decoder);
477
478 #if PLATFORM(MAC)
479     decoder->setImportanceAssertion(std::make_unique<ImportanceAssertion>(header));
480 #endif
481
482     if (decoder->messageReceiverName() == "IPC" && decoder->messageName() == "InitializeConnection") {
483         ASSERT(m_isServer);
484         ASSERT(!m_isConnected);
485         ASSERT(!m_sendPort);
486
487         MachPort port;
488         if (!decoder->decode(port)) {
489             // FIXME: Disconnect.
490             return;
491         }
492
493         m_sendPort = port.port();
494         
495         if (m_sendPort) {
496             initializeDeadNameSource();
497             dispatch_resume(m_deadNameSource);
498         }
499
500         m_isConnected = true;
501
502         // Send any pending outgoing messages.
503         sendOutgoingMessages();
504         
505         return;
506     }
507
508 #if !PLATFORM(IOS)
509     if (decoder->messageReceiverName() == "IPC" && decoder->messageName() == "SetExceptionPort") {
510         if (m_isServer) {
511             // Server connections aren't supposed to have their exception ports overriden. Treat this as an invalid message.
512             RefPtr<Connection> protectedThis(this);
513             StringReference messageReceiverName = decoder->messageReceiverName();
514             StringCapture capturedMessageReceiverName(String(messageReceiverName.data(), messageReceiverName.size()));
515             StringReference messageName = decoder->messageName();
516             StringCapture capturedMessageName(String(messageName.data(), messageName.size()));
517             m_clientRunLoop.dispatch([protectedThis, capturedMessageReceiverName, capturedMessageName] {
518                 protectedThis->dispatchDidReceiveInvalidMessage(capturedMessageReceiverName.string().utf8(), capturedMessageName.string().utf8());
519             });
520             return;
521         }
522         MachPort exceptionPort;
523         if (!decoder->decode(exceptionPort))
524             return;
525
526         setMachExceptionPort(exceptionPort.port());
527         return;
528     }
529 #endif
530
531     processIncomingMessage(WTF::move(decoder));
532 }    
533
534 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED <= 101000
535 void Connection::exceptionSourceEventHandler()
536 {
537     ReceiveBuffer buffer;
538
539     mach_msg_header_t* header = readFromMachPort(m_exceptionPort, buffer);
540     if (!header)
541         return;
542
543     // We've read the exception message. Now send it on to the real exception port.
544
545     // The remote port should have a send once right.
546     ASSERT(MACH_MSGH_BITS_REMOTE(header->msgh_bits) == MACH_MSG_TYPE_MOVE_SEND_ONCE);
547
548     // Now get the real exception port.
549     mach_port_t exceptionPort = machExceptionPort();
550
551     // First, get the complex bit from the source message.
552     mach_msg_bits_t messageBits = header->msgh_bits & MACH_MSGH_BITS_COMPLEX;
553     messageBits |= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MOVE_SEND_ONCE);
554
555     header->msgh_bits = messageBits;
556     header->msgh_local_port = header->msgh_remote_port;
557     header->msgh_remote_port = exceptionPort;
558
559     // Now send along the message.
560     kern_return_t kr = mach_msg(header, MACH_SEND_MSG, header->msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
561     if (kr != KERN_SUCCESS)
562         LOG_ERROR("Failed to send message to real exception port. %s (%x)", mach_error_string(kr), kr);
563
564     connectionDidClose();
565 }
566
567 void Connection::setShouldCloseConnectionOnMachExceptions()
568 {
569     ASSERT(m_exceptionPort == MACH_PORT_NULL);
570
571     if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &m_exceptionPort) != KERN_SUCCESS)
572         ASSERT_NOT_REACHED();
573
574     if (mach_port_insert_right(mach_task_self(), m_exceptionPort, m_exceptionPort, MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS)
575         ASSERT_NOT_REACHED();
576 }
577 #endif
578
579 IPC::Connection::Identifier Connection::identifier() const
580 {
581     return Identifier(m_isServer ? m_receivePort : m_sendPort, m_xpcConnection);
582 }
583
584 bool Connection::getAuditToken(audit_token_t& auditToken)
585 {
586     if (!m_xpcConnection)
587         return false;
588     
589     xpc_connection_get_audit_token(m_xpcConnection.get(), &auditToken);
590     return true;
591 }
592
593 bool Connection::kill()
594 {
595     if (m_xpcConnection) {
596         xpc_connection_kill(m_xpcConnection.get(), SIGKILL);
597         return true;
598     }
599
600     return false;
601 }
602     
603 void Connection::willSendSyncMessage(unsigned flags)
604 {
605 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
606     if ((flags & InformPlatformProcessWillSuspend) && WebCore::AXObjectCache::accessibilityEnabled())
607         _AXUIElementNotifyProcessSuspendStatus(AXSuspendStatusSuspended);
608 #endif
609 }
610
611 void Connection::didReceiveSyncReply(unsigned flags)
612 {
613 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
614     if ((flags & InformPlatformProcessWillSuspend) && WebCore::AXObjectCache::accessibilityEnabled())
615         _AXUIElementNotifyProcessSuspendStatus(AXSuspendStatusRunning);
616 #endif
617 }
618
619 pid_t Connection::remoteProcessID() const
620 {
621     if (!m_xpcConnection)
622         return 0;
623
624     return xpc_connection_get_pid(m_xpcConnection.get());
625 }
626     
627 } // namespace IPC