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