]>
Commit | Line | Data |
---|---|---|
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 | ||
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}; | |
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 | ||
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 | ||
ed1e77d3 | 153 | bool 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 | ||
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 | { | |
ed1e77d3 | 227 | RemoteInspector::singleton().sendMessageToRemoteFrontend(identifier(), message); |
81345200 A |
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}; | |
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 | ||
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) |