]> git.saurik.com Git - apple/javascriptcore.git/blame - inspector/remote/RemoteInspectorDebuggableConnection.mm
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / inspector / remote / RemoteInspectorDebuggableConnection.mm
CommitLineData
81345200
A
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"
ed1e77d3 33#import <dispatch/dispatch.h>
81345200
A
34#import <wtf/Vector.h>
35
36#if PLATFORM(IOS)
37#import <wtf/ios/WebCoreThread.h>
38#endif
39
40namespace Inspector {
41
42static std::mutex* rwiQueueMutex;
43static CFRunLoopSourceRef rwiRunLoopSource;
44static RemoteInspectorQueue* rwiQueue;
45
46static 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
64static 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
79static 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};
ed1e77d3 87 rwiRunLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 1, &runLoopSourceContext);
81345200
A
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
95static 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
111RemoteInspectorDebuggableConnection::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
121RemoteInspectorDebuggableConnection::~RemoteInspectorDebuggableConnection()
122{
123 teardownRunLoop();
124}
125
126NSString *RemoteInspectorDebuggableConnection::destination() const
127{
128 return [[m_destination copy] autorelease];
129}
130
131NSString *RemoteInspectorDebuggableConnection::connectionIdentifier() const
132{
133 return [[m_connectionIdentifier copy] autorelease];
134}
135
136void 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
ed1e77d3 153bool RemoteInspectorDebuggableConnection::setup(bool isAutomaticInspection, bool automaticallyPause)
81345200
A
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()) {
ed1e77d3 165 RemoteInspector::singleton().setupFailed(identifier());
81345200
A
166 m_debuggable = nullptr;
167 } else {
ed1e77d3 168 m_debuggable->connect(this, isAutomaticInspection);
81345200 169 m_connected = true;
ed1e77d3
A
170
171 if (automaticallyPause)
172 m_debuggable->pause();
81345200
A
173 }
174 }
175 deref();
176 });
177
178 return true;
179}
180
181void RemoteInspectorDebuggableConnection::closeFromDebuggable()
182{
183 std::lock_guard<std::mutex> lock(m_debuggableMutex);
184
185 m_debuggable = nullptr;
186}
187
188void 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
206void 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
225bool RemoteInspectorDebuggableConnection::sendMessageToFrontend(const String& message)
226{
ed1e77d3 227 RemoteInspector::singleton().sendMessageToRemoteFrontend(identifier(), message);
81345200
A
228
229 return true;
230}
231
232void 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};
ed1e77d3 243 m_runLoopSource = adoptCF(CFRunLoopSourceCreate(kCFAllocatorDefault, 1, &runLoopSourceContext));
81345200
A
244
245 CFRunLoopAddSource(m_runLoop.get(), m_runLoopSource.get(), kCFRunLoopDefaultMode);
246 CFRunLoopAddSource(m_runLoop.get(), m_runLoopSource.get(), EventLoop::remoteInspectorRunLoopMode());
247}
248
249void 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
261void 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)