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