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