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