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