]> git.saurik.com Git - apple/javascriptcore.git/blob - inspector/remote/RemoteInspectorDebuggableConnection.mm
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / inspector / remote / RemoteInspectorDebuggableConnection.mm
1 /*
2 * Copyright (C) 2013 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. ``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.
24 */
25
26 #import "config.h"
27 #import "RemoteInspectorDebuggableConnection.h"
28
29 #if ENABLE(REMOTE_INSPECTOR)
30
31 #import "EventLoop.h"
32 #import "RemoteInspector.h"
33 #import <wtf/Vector.h>
34
35 #if PLATFORM(IOS)
36 #import <wtf/ios/WebCoreThread.h>
37 #endif
38
39 namespace Inspector {
40
41 static std::mutex* rwiQueueMutex;
42 static CFRunLoopSourceRef rwiRunLoopSource;
43 static RemoteInspectorQueue* rwiQueue;
44
45 static void RemoteInspectorHandleRunSourceGlobal(void*)
46 {
47 ASSERT(CFRunLoopGetCurrent() == CFRunLoopGetMain());
48 ASSERT(rwiQueueMutex);
49 ASSERT(rwiRunLoopSource);
50 ASSERT(rwiQueue);
51
52 RemoteInspectorQueue queueCopy;
53 {
54 std::lock_guard<std::mutex> lock(*rwiQueueMutex);
55 queueCopy = *rwiQueue;
56 rwiQueue->clear();
57 }
58
59 for (const auto& block : queueCopy)
60 block();
61 }
62
63 static void RemoteInspectorQueueTaskOnGlobalQueue(void (^task)())
64 {
65 ASSERT(rwiQueueMutex);
66 ASSERT(rwiRunLoopSource);
67 ASSERT(rwiQueue);
68
69 {
70 std::lock_guard<std::mutex> lock(*rwiQueueMutex);
71 rwiQueue->append(RemoteInspectorBlock(task));
72 }
73
74 CFRunLoopSourceSignal(rwiRunLoopSource);
75 CFRunLoopWakeUp(CFRunLoopGetMain());
76 }
77
78 static void RemoteInspectorInitializeGlobalQueue()
79 {
80 static dispatch_once_t pred;
81 dispatch_once(&pred, ^{
82 rwiQueue = new RemoteInspectorQueue;
83 rwiQueueMutex = std::make_unique<std::mutex>().release();
84
85 CFRunLoopSourceContext runLoopSourceContext = {0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, RemoteInspectorHandleRunSourceGlobal};
86 rwiRunLoopSource = CFRunLoopSourceCreate(nullptr, 1, &runLoopSourceContext);
87
88 // Add to the default run loop mode for default handling, and the JSContext remote inspector run loop mode when paused.
89 CFRunLoopAddSource(CFRunLoopGetMain(), rwiRunLoopSource, kCFRunLoopDefaultMode);
90 CFRunLoopAddSource(CFRunLoopGetMain(), rwiRunLoopSource, EventLoop::remoteInspectorRunLoopMode());
91 });
92 }
93
94 static void RemoteInspectorHandleRunSourceWithInfo(void* info)
95 {
96 RemoteInspectorDebuggableConnection *debuggableConnection = static_cast<RemoteInspectorDebuggableConnection*>(info);
97
98 RemoteInspectorQueue queueCopy;
99 {
100 std::lock_guard<std::mutex> lock(debuggableConnection->queueMutex());
101 queueCopy = debuggableConnection->queue();
102 debuggableConnection->clearQueue();
103 }
104
105 for (const auto& block : queueCopy)
106 block();
107 }
108
109
110 RemoteInspectorDebuggableConnection::RemoteInspectorDebuggableConnection(RemoteInspectorDebuggable* debuggable, NSString *connectionIdentifier, NSString *destination, RemoteInspectorDebuggable::DebuggableType)
111 : m_debuggable(debuggable)
112 , m_connectionIdentifier(connectionIdentifier)
113 , m_destination(destination)
114 , m_identifier(debuggable->identifier())
115 , m_connected(false)
116 {
117 setupRunLoop();
118 }
119
120 RemoteInspectorDebuggableConnection::~RemoteInspectorDebuggableConnection()
121 {
122 teardownRunLoop();
123 }
124
125 NSString *RemoteInspectorDebuggableConnection::destination() const
126 {
127 return [[m_destination copy] autorelease];
128 }
129
130 NSString *RemoteInspectorDebuggableConnection::connectionIdentifier() const
131 {
132 return [[m_connectionIdentifier copy] autorelease];
133 }
134
135 void RemoteInspectorDebuggableConnection::dispatchAsyncOnDebuggable(void (^block)())
136 {
137 if (m_runLoop) {
138 queueTaskOnPrivateRunLoop(block);
139 return;
140 }
141
142 #if PLATFORM(IOS)
143 if (WebCoreWebThreadIsEnabled && WebCoreWebThreadIsEnabled()) {
144 WebCoreWebThreadRun(block);
145 return;
146 }
147 #endif
148
149 RemoteInspectorQueueTaskOnGlobalQueue(block);
150 }
151
152 bool RemoteInspectorDebuggableConnection::setup()
153 {
154 std::lock_guard<std::mutex> lock(m_debuggableMutex);
155
156 if (!m_debuggable)
157 return false;
158
159 ref();
160 dispatchAsyncOnDebuggable(^{
161 {
162 std::lock_guard<std::mutex> lock(m_debuggableMutex);
163 if (!m_debuggable || !m_debuggable->remoteDebuggingAllowed() || m_debuggable->hasLocalDebugger()) {
164 RemoteInspector::shared().setupFailed(identifier());
165 m_debuggable = nullptr;
166 } else {
167 m_debuggable->connect(this);
168 m_connected = true;
169 }
170 }
171 deref();
172 });
173
174 return true;
175 }
176
177 void RemoteInspectorDebuggableConnection::closeFromDebuggable()
178 {
179 std::lock_guard<std::mutex> lock(m_debuggableMutex);
180
181 m_debuggable = nullptr;
182 }
183
184 void RemoteInspectorDebuggableConnection::close()
185 {
186 ref();
187 dispatchAsyncOnDebuggable(^{
188 {
189 std::lock_guard<std::mutex> lock(m_debuggableMutex);
190
191 if (m_debuggable) {
192 if (m_connected)
193 m_debuggable->disconnect();
194
195 m_debuggable = nullptr;
196 }
197 }
198 deref();
199 });
200 }
201
202 void RemoteInspectorDebuggableConnection::sendMessageToBackend(NSString *message)
203 {
204 ref();
205 dispatchAsyncOnDebuggable(^{
206 {
207 RemoteInspectorDebuggable* debuggable = nullptr;
208 {
209 std::lock_guard<std::mutex> lock(m_debuggableMutex);
210 if (!m_debuggable)
211 return;
212 debuggable = m_debuggable;
213 }
214
215 debuggable->dispatchMessageFromRemoteFrontend(message);
216 }
217 deref();
218 });
219 }
220
221 bool RemoteInspectorDebuggableConnection::sendMessageToFrontend(const String& message)
222 {
223 RemoteInspector::shared().sendMessageToRemoteFrontend(identifier(), message);
224
225 return true;
226 }
227
228 void RemoteInspectorDebuggableConnection::setupRunLoop()
229 {
230 CFRunLoopRef debuggerRunLoop = m_debuggable->debuggerRunLoop();
231 if (!debuggerRunLoop) {
232 RemoteInspectorInitializeGlobalQueue();
233 return;
234 }
235
236 m_runLoop = debuggerRunLoop;
237
238 CFRunLoopSourceContext runLoopSourceContext = {0, this, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, RemoteInspectorHandleRunSourceWithInfo};
239 m_runLoopSource = CFRunLoopSourceCreate(nullptr, 1, &runLoopSourceContext);
240
241 CFRunLoopAddSource(m_runLoop.get(), m_runLoopSource.get(), kCFRunLoopDefaultMode);
242 CFRunLoopAddSource(m_runLoop.get(), m_runLoopSource.get(), EventLoop::remoteInspectorRunLoopMode());
243 }
244
245 void RemoteInspectorDebuggableConnection::teardownRunLoop()
246 {
247 if (!m_runLoop)
248 return;
249
250 CFRunLoopRemoveSource(m_runLoop.get(), m_runLoopSource.get(), kCFRunLoopDefaultMode);
251 CFRunLoopRemoveSource(m_runLoop.get(), m_runLoopSource.get(), EventLoop::remoteInspectorRunLoopMode());
252
253 m_runLoop = nullptr;
254 m_runLoopSource = nullptr;
255 }
256
257 void RemoteInspectorDebuggableConnection::queueTaskOnPrivateRunLoop(void (^block)())
258 {
259 ASSERT(m_runLoop);
260
261 {
262 std::lock_guard<std::mutex> lock(m_queueMutex);
263 m_queue.append(RemoteInspectorBlock(block));
264 }
265
266 CFRunLoopSourceSignal(m_runLoopSource.get());
267 CFRunLoopWakeUp(m_runLoop.get());
268 }
269
270 } // namespace Inspector
271
272 #endif // ENABLE(REMOTE_INSPECTOR)