Unreviewed, rolling out r239524.
[WebKit-https.git] / Source / WebKit / Platform / IPC / mac / ConnectionMac.mm
1 /*
2  * Copyright (C) 2010-2018 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 #import "config.h"
27 #import "Connection.h"
28
29 #import "DataReference.h"
30 #import "ImportanceAssertion.h"
31 #import "MachMessage.h"
32 #import "MachPort.h"
33 #import "MachUtilities.h"
34 #import "WKCrashReporter.h"
35 #import <WebCore/AXObjectCache.h>
36 #import <mach/mach_error.h>
37 #import <mach/vm_map.h>
38 #import <sys/mman.h>
39 #import <wtf/MachSendRight.h>
40 #import <wtf/RunLoop.h>
41 #import <wtf/spi/darwin/XPCSPI.h>
42
43 #if PLATFORM(IOS_FAMILY)
44 #import "ProcessAssertion.h"
45 #import <UIKit/UIAccessibility.h>
46
47 #if USE(APPLE_INTERNAL_SDK)
48 #import <AXRuntime/AXDefines.h>
49 #import <AXRuntime/AXNotificationConstants.h>
50 #else
51 #define kAXPidStatusChangedNotification 0
52 #endif
53
54 #endif
55
56 #if PLATFORM(MAC)
57
58 #if USE(APPLE_INTERNAL_SDK)
59 #import <HIServices/AccessibilityPriv.h>
60 #else
61 typedef enum {
62     AXSuspendStatusRunning = 0,
63     AXSuspendStatusSuspended,
64 } AXSuspendStatus;
65 #endif
66
67 extern "C" AXError _AXUIElementNotifyProcessSuspendStatus(AXSuspendStatus);
68
69 #endif // PLATFORM(MAC)
70
71 namespace IPC {
72
73 static const size_t inlineMessageMaxSize = 4096;
74
75 // Arbitrary message IDs that do not collide with Mach notification messages (used my initials).
76 constexpr mach_msg_id_t inlineBodyMessageID = 0xdba0dba;
77 constexpr mach_msg_id_t outOfLineBodyMessageID = 0xdba1dba;
78
79 // ConnectionTerminationWatchdog does two things:
80 // 1) It sets a watchdog timer to kill the peered process.
81 // 2) On iOS, make the process runnable for the duration of the watchdog
82 //    to ensure it has a chance to terminate cleanly.
83 class ConnectionTerminationWatchdog {
84 public:
85     static void createConnectionTerminationWatchdog(OSObjectPtr<xpc_connection_t>& xpcConnection, Seconds interval)
86     {
87         new ConnectionTerminationWatchdog(xpcConnection, interval);
88     }
89     
90 private:
91     ConnectionTerminationWatchdog(OSObjectPtr<xpc_connection_t>& xpcConnection, Seconds interval)
92         : m_xpcConnection(xpcConnection)
93         , m_watchdogTimer(RunLoop::main(), this, &ConnectionTerminationWatchdog::watchdogTimerFired)
94 #if PLATFORM(IOS_FAMILY)
95         , m_assertion(std::make_unique<WebKit::ProcessAndUIAssertion>(xpc_connection_get_pid(m_xpcConnection.get()), WebKit::AssertionState::Background))
96 #endif
97     {
98         m_watchdogTimer.startOneShot(interval);
99     }
100     
101     void watchdogTimerFired()
102     {
103         xpc_connection_kill(m_xpcConnection.get(), SIGKILL);
104         delete this;
105     }
106
107     OSObjectPtr<xpc_connection_t> m_xpcConnection;
108     RunLoop::Timer<ConnectionTerminationWatchdog> m_watchdogTimer;
109 #if PLATFORM(IOS_FAMILY)
110     std::unique_ptr<WebKit::ProcessAndUIAssertion> m_assertion;
111 #endif
112 };
113     
114 void Connection::platformInvalidate()
115 {
116     if (!m_isConnected) {
117         if (m_sendPort) {
118             ASSERT(!m_isServer);
119             deallocateSendRightSafely(m_sendPort);
120             m_sendPort = MACH_PORT_NULL;
121         }
122
123         if (m_receiveSource) {
124             // For a short period of time, when m_isServer is true and open() has been called, m_receiveSource has been initialized
125             // but m_isConnected has not been set to true yet. In this case, we need to cancel m_receiveSource instead of destroying
126             // m_receivePort ourselves.
127             ASSERT(m_isServer);
128             cancelReceiveSource();
129         }
130
131         if (m_receivePort) {
132             ASSERT(m_isServer);
133 #if !PLATFORM(WATCHOS)
134             mach_port_unguard(mach_task_self(), m_receivePort, reinterpret_cast<mach_port_context_t>(this));
135 #endif
136             mach_port_mod_refs(mach_task_self(), m_receivePort, MACH_PORT_RIGHT_RECEIVE, -1);
137             m_receivePort = MACH_PORT_NULL;
138         }
139
140         return;
141     }
142
143     m_pendingOutgoingMachMessage = nullptr;
144     m_isInitializingSendSource = false;
145     m_isConnected = false;
146
147     ASSERT(m_sendPort);
148     ASSERT(m_receivePort);
149
150     // Unregister our ports.
151     dispatch_source_cancel(m_sendSource);
152     dispatch_release(m_sendSource);
153     m_sendSource = nullptr;
154     m_sendPort = MACH_PORT_NULL;
155
156     cancelReceiveSource();
157 }
158
159 void Connection::cancelReceiveSource()
160 {
161     dispatch_source_cancel(m_receiveSource);
162     dispatch_release(m_receiveSource);
163     m_receiveSource = nullptr;
164     m_receivePort = MACH_PORT_NULL;
165 }
166     
167 void Connection::terminateSoon(Seconds interval)
168 {
169     if (m_xpcConnection)
170         ConnectionTerminationWatchdog::createConnectionTerminationWatchdog(m_xpcConnection, interval);
171 }
172     
173 void Connection::platformInitialize(Identifier identifier)
174 {
175     if (!MACH_PORT_VALID(identifier.port))
176         return;
177
178     if (m_isServer) {
179         m_receivePort = identifier.port;
180         m_sendPort = MACH_PORT_NULL;
181
182 #if !PLATFORM(WATCHOS)
183         mach_port_guard(mach_task_self(), m_receivePort, reinterpret_cast<mach_port_context_t>(this), true);
184 #endif
185     } else {
186         m_receivePort = MACH_PORT_NULL;
187         m_sendPort = identifier.port;
188     }
189
190     m_sendSource = nullptr;
191     m_receiveSource = nullptr;
192
193     m_xpcConnection = identifier.xpcConnection;
194 }
195
196 bool Connection::open()
197 {
198     if (m_isServer) {
199         ASSERT(m_receivePort);
200         ASSERT(!m_sendPort);
201         ASSERT(MACH_PORT_VALID(m_receivePort));
202     } else {
203         ASSERT(!m_receivePort);
204         ASSERT(m_sendPort);
205         ASSERT(MACH_PORT_VALID(m_sendPort));
206
207         auto kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &m_receivePort);
208         if (kr != KERN_SUCCESS) {
209             LOG_ERROR("Could not allocate mach port, error %x: %s", kr, mach_error_string(kr));
210             CRASH();
211         }
212 #if !PLATFORM(WATCHOS)
213         mach_port_guard(mach_task_self(), m_receivePort, reinterpret_cast<mach_port_context_t>(this), true);
214 #endif
215
216 #if PLATFORM(MAC)
217         mach_port_set_attributes(mach_task_self(), m_receivePort, MACH_PORT_DENAP_RECEIVER, (mach_port_info_t)0, 0);
218 #endif
219
220         m_isConnected = true;
221         
222         // Send the initialize message, which contains a send right for the server to use.
223         auto encoder = std::make_unique<Encoder>("IPC", "InitializeConnection", 0);
224         encoder->encode(MachPort(m_receivePort, MACH_MSG_TYPE_MAKE_SEND));
225
226         initializeSendSource();
227
228         sendMessage(WTFMove(encoder), { });
229     }
230
231     // Change the message queue length for the receive port.
232     setMachPortQueueLength(m_receivePort, MACH_PORT_QLIMIT_LARGE);
233
234     RefPtr<Connection> connection(this);
235     m_receiveSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, m_receivePort, 0, m_connectionQueue->dispatchQueue());
236     dispatch_source_set_event_handler(m_receiveSource, [connection] {
237         connection->receiveSourceEventHandler();
238     });
239     dispatch_source_set_cancel_handler(m_receiveSource, [connection, receivePort = m_receivePort] {
240 #if PLATFORM(WATCHOS)
241         UNUSED_PARAM(connection);
242 #else
243         mach_port_unguard(mach_task_self(), receivePort, reinterpret_cast<mach_port_context_t>(connection.get()));
244 #endif
245         mach_port_mod_refs(mach_task_self(), receivePort, MACH_PORT_RIGHT_RECEIVE, -1);
246     });
247
248     ref();
249     dispatch_async(m_connectionQueue->dispatchQueue(), ^{
250         dispatch_resume(m_receiveSource);
251
252         if (m_sendSource)
253             dispatch_resume(m_sendSource);
254
255         deref();
256     });
257
258     return true;
259 }
260
261 bool Connection::sendMessage(std::unique_ptr<MachMessage> message)
262 {
263     ASSERT(message);
264     ASSERT(!m_pendingOutgoingMachMessage);
265     ASSERT(!m_isInitializingSendSource);
266
267     // Send the message.
268     kern_return_t kr = mach_msg(message->header(), MACH_SEND_MSG | MACH_SEND_TIMEOUT | MACH_SEND_NOTIFY, message->size(), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
269     switch (kr) {
270     case MACH_MSG_SUCCESS:
271         // The kernel has already adopted the descriptors.
272         message->leakDescriptors();
273         return true;
274
275     case MACH_SEND_TIMED_OUT:
276         // We timed out, stash away the message for later.
277         m_pendingOutgoingMachMessage = WTFMove(message);
278         return false;
279
280     case MACH_SEND_INVALID_DEST:
281         // The other end has disappeared, we'll get a dead name notification which will cause us to be invalidated.
282         return false;
283
284     default:
285         WebKit::setCrashReportApplicationSpecificInformation((__bridge CFStringRef)[NSString stringWithFormat:@"Unhandled error code %x, message '%s::%s'", kr, message->messageReceiverName().data(), message->messageName().data()]);
286         CRASH();
287     }
288 }
289
290 bool Connection::platformCanSendOutgoingMessages() const
291 {
292     return !m_pendingOutgoingMachMessage && !m_isInitializingSendSource;
293 }
294
295 bool Connection::sendOutgoingMessage(std::unique_ptr<Encoder> encoder)
296 {
297     ASSERT(!m_pendingOutgoingMachMessage && !m_isInitializingSendSource);
298
299     auto attachments = encoder->releaseAttachments();
300     
301     auto numberOfPortDescriptors = std::count_if(attachments.begin(), attachments.end(), [](auto& attachment) { return attachment.type() == Attachment::MachPortType; });
302     bool messageBodyIsOOL = false;
303     auto messageSize = MachMessage::messageSize(encoder->bufferSize(), numberOfPortDescriptors, messageBodyIsOOL);
304     if (messageSize > inlineMessageMaxSize) {
305         messageBodyIsOOL = true;
306         messageSize = MachMessage::messageSize(0, numberOfPortDescriptors, messageBodyIsOOL);
307     }
308
309     auto message = MachMessage::create(messageSize);
310     message->setMessageReceiverName(encoder->messageReceiverName().toString());
311     message->setMessageName(encoder->messageName().toString());
312
313     auto* header = message->header();
314     header->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
315     header->msgh_size = messageSize;
316     header->msgh_remote_port = m_sendPort;
317     header->msgh_local_port = MACH_PORT_NULL;
318     header->msgh_id = inlineBodyMessageID;
319
320     auto* messageData = reinterpret_cast<uint8_t*>(header + 1);
321
322     bool isComplex = numberOfPortDescriptors || messageBodyIsOOL;
323     if (isComplex) {
324         header->msgh_bits |= MACH_MSGH_BITS_COMPLEX;
325
326         auto* body = reinterpret_cast<mach_msg_body_t*>(messageData);
327         body->msgh_descriptor_count = numberOfPortDescriptors + messageBodyIsOOL;
328         messageData = reinterpret_cast<uint8_t*>(body + 1);
329
330         auto getDescriptorAndSkip = [](uint8_t*& data) {
331             return reinterpret_cast<mach_msg_descriptor_t*>(std::exchange(data, data + sizeof(mach_msg_port_descriptor_t)));
332         };
333
334         for (auto& attachment : attachments) {
335             ASSERT(attachment.type() == Attachment::MachPortType);
336             if (attachment.type() == Attachment::MachPortType) {
337                 auto* descriptor = getDescriptorAndSkip(messageData);
338                 descriptor->port.name = attachment.port();
339                 descriptor->port.disposition = attachment.disposition();
340                 descriptor->port.type = MACH_MSG_PORT_DESCRIPTOR;
341             }
342         }
343
344         if (messageBodyIsOOL) {
345             header->msgh_id = outOfLineBodyMessageID;
346
347             auto* descriptor = getDescriptorAndSkip(messageData);
348             descriptor->out_of_line.address = encoder->buffer();
349             descriptor->out_of_line.size = encoder->bufferSize();
350             descriptor->out_of_line.copy = MACH_MSG_VIRTUAL_COPY;
351             descriptor->out_of_line.deallocate = false;
352             descriptor->out_of_line.type = MACH_MSG_OOL_DESCRIPTOR;
353         }
354     }
355
356     // Copy the data if it is not being sent out-of-line.
357     if (!messageBodyIsOOL)
358         memcpy(messageData, encoder->buffer(), encoder->bufferSize());
359
360     ASSERT(m_sendPort);
361     ASSERT(MACH_PORT_VALID(m_sendPort));
362
363     return sendMessage(WTFMove(message));
364 }
365
366 void Connection::initializeSendSource()
367 {
368     m_sendSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_SEND, m_sendPort, DISPATCH_MACH_SEND_DEAD | DISPATCH_MACH_SEND_POSSIBLE, m_connectionQueue->dispatchQueue());
369     m_isInitializingSendSource = true;
370
371     RefPtr<Connection> connection(this);
372     dispatch_source_set_registration_handler(m_sendSource, [connection] {
373         if (!connection->m_sendSource)
374             return;
375         connection->m_isInitializingSendSource = false;
376         connection->resumeSendSource();
377     });
378     dispatch_source_set_event_handler(m_sendSource, [connection] {
379         if (!connection->m_sendSource)
380             return;
381
382         unsigned long data = dispatch_source_get_data(connection->m_sendSource);
383
384         if (data & DISPATCH_MACH_SEND_DEAD) {
385             connection->connectionDidClose();
386             return;
387         }
388
389         if (data & DISPATCH_MACH_SEND_POSSIBLE) {
390             // FIXME: Figure out why we get spurious DISPATCH_MACH_SEND_POSSIBLE events.
391             connection->resumeSendSource();
392             return;
393         }
394     });
395
396     ASSERT(MACH_PORT_VALID(m_sendPort));
397     mach_port_t sendPort = m_sendPort;
398     dispatch_source_set_cancel_handler(m_sendSource, ^{
399         // Release our send right.
400         deallocateSendRightSafely(sendPort);
401     });
402 }
403
404 void Connection::resumeSendSource()
405 {
406     ASSERT(!m_isInitializingSendSource);
407     if (m_pendingOutgoingMachMessage)
408         sendMessage(WTFMove(m_pendingOutgoingMachMessage));
409     sendOutgoingMessages();
410 }
411
412 static std::unique_ptr<Decoder> createMessageDecoder(mach_msg_header_t* header)
413 {
414     if (!(header->msgh_bits & MACH_MSGH_BITS_COMPLEX)) {
415         // We have a simple message.
416         uint8_t* body = reinterpret_cast<uint8_t*>(header + 1);
417         size_t bodySize = header->msgh_size - sizeof(mach_msg_header_t);
418
419         return std::make_unique<Decoder>(body, bodySize, nullptr, Vector<Attachment> { });
420     }
421
422     bool messageBodyIsOOL = header->msgh_id == outOfLineBodyMessageID;
423
424     mach_msg_body_t* body = reinterpret_cast<mach_msg_body_t*>(header + 1);
425     mach_msg_size_t numDescriptors = body->msgh_descriptor_count;
426     ASSERT(numDescriptors);
427
428     uint8_t* descriptorData = reinterpret_cast<uint8_t*>(body + 1);
429
430     // If the message body was sent out-of-line, don't treat the last descriptor
431     // as an attachment, since it is really the message body.
432     if (messageBodyIsOOL)
433         --numDescriptors;
434
435     // Build attachment list
436     Vector<Attachment> attachments(numDescriptors);
437
438     for (mach_msg_size_t i = 0; i < numDescriptors; ++i) {
439         mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);
440         ASSERT(descriptor->type.type == MACH_MSG_PORT_DESCRIPTOR);
441         if (descriptor->type.type != MACH_MSG_PORT_DESCRIPTOR)
442             return nullptr;
443
444         attachments[numDescriptors - i - 1] = Attachment(descriptor->port.name, descriptor->port.disposition);
445         descriptorData += sizeof(mach_msg_port_descriptor_t);
446     }
447
448     if (messageBodyIsOOL) {
449         mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);
450         ASSERT(descriptor->type.type == MACH_MSG_OOL_DESCRIPTOR);
451         if (descriptor->type.type != MACH_MSG_OOL_DESCRIPTOR)
452             return nullptr;
453
454         uint8_t* messageBody = static_cast<uint8_t*>(descriptor->out_of_line.address);
455         size_t messageBodySize = descriptor->out_of_line.size;
456
457         return std::make_unique<Decoder>(messageBody, messageBodySize, [](const uint8_t* buffer, size_t length) {
458             vm_deallocate(mach_task_self(), reinterpret_cast<vm_address_t>(buffer), length);
459         }, WTFMove(attachments));
460     }
461
462     uint8_t* messageBody = descriptorData;
463     size_t messageBodySize = header->msgh_size - (descriptorData - reinterpret_cast<uint8_t*>(header));
464
465     return std::make_unique<Decoder>(messageBody, messageBodySize, nullptr, WTFMove(attachments));
466 }
467
468 // The receive buffer size should always include the maximum trailer size.
469 static const size_t receiveBufferSize = inlineMessageMaxSize + MAX_TRAILER_SIZE;
470 typedef Vector<char, receiveBufferSize> ReceiveBuffer;
471
472 static mach_msg_header_t* readFromMachPort(mach_port_t machPort, ReceiveBuffer& buffer)
473 {
474     ASSERT(MACH_PORT_VALID(machPort));
475
476     buffer.resize(receiveBufferSize);
477
478     mach_msg_header_t* header = reinterpret_cast<mach_msg_header_t*>(buffer.data());
479     kern_return_t kr = mach_msg(header, MACH_RCV_MSG | MACH_RCV_LARGE | MACH_RCV_TIMEOUT, 0, buffer.size(), machPort, 0, MACH_PORT_NULL);
480     if (kr == MACH_RCV_TIMED_OUT)
481         return nullptr;
482
483     if (kr == MACH_RCV_TOO_LARGE) {
484         // The message was too large, resize the buffer and try again.
485         buffer.resize(header->msgh_size + MAX_TRAILER_SIZE);
486         header = reinterpret_cast<mach_msg_header_t*>(buffer.data());
487         
488         kr = mach_msg(header, MACH_RCV_MSG | MACH_RCV_LARGE | MACH_RCV_TIMEOUT, 0, buffer.size(), machPort, 0, MACH_PORT_NULL);
489         ASSERT(kr != MACH_RCV_TOO_LARGE);
490     }
491
492     if (kr != MACH_MSG_SUCCESS) {
493 #if !ASSERT_DISABLED
494         WebKit::setCrashReportApplicationSpecificInformation((__bridge CFStringRef)[NSString stringWithFormat:@"Unhandled error code %x from mach_msg, receive port is %x", kr, machPort]);
495 #endif
496         ASSERT_NOT_REACHED();
497         return nullptr;
498     }
499
500     return header;
501 }
502
503 void Connection::receiveSourceEventHandler()
504 {
505     ReceiveBuffer buffer;
506
507     ASSERT(MACH_PORT_VALID(m_receivePort));
508     mach_msg_header_t* header = readFromMachPort(m_receivePort, buffer);
509     if (!header)
510         return;
511
512     switch (header->msgh_id) {
513     case MACH_NOTIFY_NO_SENDERS:
514         ASSERT(m_isServer);
515         if (!m_sendPort)
516             connectionDidClose();
517         return;
518
519     case inlineBodyMessageID:
520     case outOfLineBodyMessageID:
521         break;
522
523     case MACH_NOTIFY_SEND_ONCE:
524     default:
525         return;
526     }
527
528     std::unique_ptr<Decoder> decoder = createMessageDecoder(header);
529     if (!decoder)
530         return;
531
532 #if PLATFORM(MAC)
533     decoder->setImportanceAssertion(std::make_unique<ImportanceAssertion>(header));
534 #endif
535
536     if (decoder->messageReceiverName() == "IPC" && decoder->messageName() == "InitializeConnection") {
537         ASSERT(m_isServer);
538         ASSERT(!m_isConnected);
539         ASSERT(!m_sendPort);
540
541         MachPort port;
542         if (!decoder->decode(port)) {
543             // FIXME: Disconnect.
544             return;
545         }
546
547         m_sendPort = port.port();
548         
549         if (m_sendPort) {
550             ASSERT(MACH_PORT_VALID(m_receivePort));
551             mach_port_t previousNotificationPort = MACH_PORT_NULL;
552             auto kr = mach_port_request_notification(mach_task_self(), m_receivePort, MACH_NOTIFY_NO_SENDERS, 0, MACH_PORT_NULL, MACH_MSG_TYPE_MOVE_SEND_ONCE, &previousNotificationPort);
553             ASSERT(kr == KERN_SUCCESS);
554             if (kr != KERN_SUCCESS) {
555                 // If mach_port_request_notification fails, 'previousNotificationPort' will be uninitialized.
556                 LOG_ERROR("mach_port_request_notification failed: (%x) %s", kr, mach_error_string(kr));
557                 previousNotificationPort = MACH_PORT_NULL;
558             }
559
560             if (previousNotificationPort != MACH_PORT_NULL)
561                 deallocateSendRightSafely(previousNotificationPort);
562
563             initializeSendSource();
564             dispatch_resume(m_sendSource);
565         }
566
567         m_isConnected = true;
568
569         // Send any pending outgoing messages.
570         sendOutgoingMessages();
571         
572         return;
573     }
574
575 #if !PLATFORM(IOS_FAMILY)
576     if (decoder->messageReceiverName() == "IPC" && decoder->messageName() == "SetExceptionPort") {
577         if (m_isServer) {
578             // Server connections aren't supposed to have their exception ports overridden. Treat this as an invalid message.
579             StringReference messageReceiverNameReference = decoder->messageReceiverName();
580             String messageReceiverName(String(messageReceiverNameReference.data(), messageReceiverNameReference.size()));
581             StringReference messageNameReference = decoder->messageName();
582             String messageName(String(messageNameReference.data(), messageNameReference.size()));
583
584             RunLoop::main().dispatch([protectedThis = makeRef(*this), messageReceiverName = WTFMove(messageReceiverName), messageName = WTFMove(messageName)]() mutable {
585                 protectedThis->dispatchDidReceiveInvalidMessage(messageReceiverName.utf8(), messageName.utf8());
586             });
587             return;
588         }
589         MachPort exceptionPort;
590         if (!decoder->decode(exceptionPort))
591             return;
592
593         setMachExceptionPort(exceptionPort.port());
594         return;
595     }
596 #endif
597
598     processIncomingMessage(WTFMove(decoder));
599 }    
600
601 IPC::Connection::Identifier Connection::identifier() const
602 {
603     return Identifier(m_isServer ? m_receivePort : m_sendPort, m_xpcConnection);
604 }
605
606 bool Connection::getAuditToken(audit_token_t& auditToken)
607 {
608     if (!m_xpcConnection)
609         return false;
610     
611     xpc_connection_get_audit_token(m_xpcConnection.get(), &auditToken);
612     return true;
613 }
614
615 bool Connection::kill()
616 {
617     if (m_xpcConnection) {
618         xpc_connection_kill(m_xpcConnection.get(), SIGKILL);
619         m_wasKilled = true;
620         return true;
621     }
622
623     return false;
624 }
625     
626 static void AccessibilityProcessSuspendedNotification(bool suspended)
627 {
628 #if PLATFORM(MAC)
629     _AXUIElementNotifyProcessSuspendStatus(suspended ? AXSuspendStatusSuspended : AXSuspendStatusRunning);
630 #elif PLATFORM(IOS_FAMILY)
631     UIAccessibilityPostNotification(kAXPidStatusChangedNotification, @{ @"pid" : @(getpid()), @"suspended" : @(suspended) });
632 #else
633     UNUSED_PARAM(suspended);
634 #endif
635 }
636     
637 void Connection::willSendSyncMessage(OptionSet<SendSyncOption> sendSyncOptions)
638 {
639     if (sendSyncOptions.contains(IPC::SendSyncOption::InformPlatformProcessWillSuspend) && WebCore::AXObjectCache::accessibilityEnabled())
640         AccessibilityProcessSuspendedNotification(true);
641 }
642
643 void Connection::didReceiveSyncReply(OptionSet<SendSyncOption> sendSyncOptions)
644 {
645     if (sendSyncOptions.contains(IPC::SendSyncOption::InformPlatformProcessWillSuspend) && WebCore::AXObjectCache::accessibilityEnabled())
646         AccessibilityProcessSuspendedNotification(false);
647 }
648
649 pid_t Connection::remoteProcessID() const
650 {
651     if (!m_xpcConnection)
652         return 0;
653
654     return xpc_connection_get_pid(m_xpcConnection.get());
655 }
656     
657 } // namespace IPC