2 * Copyright (C) 2013 Apple Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #import "RemoteInspectorXPCConnection.h"
29 #if ENABLE(REMOTE_INSPECTOR)
31 #import <Foundation/Foundation.h>
32 #import <wtf/Assertions.h>
35 #if __has_include(<CoreFoundation/CFXPCBridge.h>)
36 #import <CoreFoundation/CFXPCBridge.h>
38 extern "C" xpc_object_t _CFXPCCreateXPCMessageWithCFObject(CFTypeRef);
39 extern "C" CFTypeRef _CFXPCCreateCFObjectFromXPCMessage(xpc_object_t);
44 // Constants private to this file for message serialization on both ends.
45 #define RemoteInspectorXPCConnectionMessageNameKey @"messageName"
46 #define RemoteInspectorXPCConnectionUserInfoKey @"userInfo"
47 #define RemoteInspectorXPCConnectionSerializedMessageKey "msgData"
49 RemoteInspectorXPCConnection::RemoteInspectorXPCConnection(xpc_connection_t connection, dispatch_queue_t queue, Client* client)
50 : m_connection(connection)
55 dispatch_retain(m_queue);
57 xpc_retain(m_connection);
58 xpc_connection_set_target_queue(m_connection, m_queue);
59 xpc_connection_set_event_handler(m_connection, ^(xpc_object_t object) {
63 // Balanced by deref when the xpc_connection receives XPC_ERROR_CONNECTION_INVALID.
66 xpc_connection_resume(m_connection);
69 RemoteInspectorXPCConnection::~RemoteInspectorXPCConnection()
72 ASSERT(!m_connection);
76 void RemoteInspectorXPCConnection::close()
78 std::lock_guard<std::mutex> lock(m_mutex);
82 void RemoteInspectorXPCConnection::closeFromMessage()
87 dispatch_async(m_queue, ^{
88 std::lock_guard<std::mutex> lock(m_mutex);
89 // This will trigger one last XPC_ERROR_CONNECTION_INVALID event on the queue and deref us.
94 void RemoteInspectorXPCConnection::closeOnQueue()
97 xpc_connection_cancel(m_connection);
98 xpc_release(m_connection);
103 dispatch_release(m_queue);
108 NSDictionary *RemoteInspectorXPCConnection::deserializeMessage(xpc_object_t object)
110 if (xpc_get_type(object) != XPC_TYPE_DICTIONARY)
113 xpc_object_t xpcDictionary = xpc_dictionary_get_value(object, RemoteInspectorXPCConnectionSerializedMessageKey);
114 if (!xpcDictionary || xpc_get_type(xpcDictionary) != XPC_TYPE_DICTIONARY) {
115 std::lock_guard<std::mutex> lock(m_mutex);
117 m_client->xpcConnectionUnhandledMessage(this, object);
121 NSDictionary *dictionary = static_cast<NSDictionary *>(_CFXPCCreateCFObjectFromXPCMessage(xpcDictionary));
122 ASSERT_WITH_MESSAGE(dictionary, "Unable to deserialize xpc message");
123 return [dictionary autorelease];
126 void RemoteInspectorXPCConnection::handleEvent(xpc_object_t object)
128 if (xpc_get_type(object) == XPC_TYPE_ERROR) {
130 std::lock_guard<std::mutex> lock(m_mutex);
132 m_client->xpcConnectionFailed(this);
139 if (object == XPC_ERROR_CONNECTION_INVALID) {
140 // This is the last event we will ever receive from the connection.
141 // This balances the ref() in the constructor.
147 NSDictionary *dataDictionary = deserializeMessage(object);
151 NSString *message = [dataDictionary objectForKey:RemoteInspectorXPCConnectionMessageNameKey];
152 NSDictionary *userInfo = [dataDictionary objectForKey:RemoteInspectorXPCConnectionUserInfoKey];
153 std::lock_guard<std::mutex> lock(m_mutex);
155 m_client->xpcConnectionReceivedMessage(this, message, userInfo);
158 void RemoteInspectorXPCConnection::sendMessage(NSString *messageName, NSDictionary *userInfo)
164 NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObject:messageName forKey:RemoteInspectorXPCConnectionMessageNameKey];
166 [dictionary setObject:userInfo forKey:RemoteInspectorXPCConnectionUserInfoKey];
168 xpc_object_t xpcDictionary = _CFXPCCreateXPCMessageWithCFObject((CFDictionaryRef)dictionary);
169 ASSERT_WITH_MESSAGE(xpcDictionary && xpc_get_type(xpcDictionary) == XPC_TYPE_DICTIONARY, "Unable to serialize xpc message");
173 xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0);
174 xpc_dictionary_set_value(msg, RemoteInspectorXPCConnectionSerializedMessageKey, xpcDictionary);
175 xpc_release(xpcDictionary);
177 xpc_connection_send_message(m_connection, msg);
182 } // namespace Inspector
184 #endif // ENABLE(REMOTE_INSPECTOR)