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