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 "RemoteInspectorDebuggableConnection.h"
29 #if ENABLE(REMOTE_INSPECTOR)
32 #import "RemoteInspector.h"
33 #import <wtf/Vector.h>
36 #import <wtf/ios/WebCoreThread.h>
41 static std::mutex* rwiQueueMutex;
42 static CFRunLoopSourceRef rwiRunLoopSource;
43 static RemoteInspectorQueue* rwiQueue;
45 static void RemoteInspectorHandleRunSourceGlobal(void*)
47 ASSERT(CFRunLoopGetCurrent() == CFRunLoopGetMain());
48 ASSERT(rwiQueueMutex);
49 ASSERT(rwiRunLoopSource);
52 RemoteInspectorQueue queueCopy;
54 std::lock_guard<std::mutex> lock(*rwiQueueMutex);
55 queueCopy = *rwiQueue;
59 for (const auto& block : queueCopy)
63 static void RemoteInspectorQueueTaskOnGlobalQueue(void (^task)())
65 ASSERT(rwiQueueMutex);
66 ASSERT(rwiRunLoopSource);
70 std::lock_guard<std::mutex> lock(*rwiQueueMutex);
71 rwiQueue->append(RemoteInspectorBlock(task));
74 CFRunLoopSourceSignal(rwiRunLoopSource);
75 CFRunLoopWakeUp(CFRunLoopGetMain());
78 static void RemoteInspectorInitializeGlobalQueue()
80 static dispatch_once_t pred;
81 dispatch_once(&pred, ^{
82 rwiQueue = new RemoteInspectorQueue;
83 rwiQueueMutex = std::make_unique<std::mutex>().release();
85 CFRunLoopSourceContext runLoopSourceContext = {0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, RemoteInspectorHandleRunSourceGlobal};
86 rwiRunLoopSource = CFRunLoopSourceCreate(nullptr, 1, &runLoopSourceContext);
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());
94 static void RemoteInspectorHandleRunSourceWithInfo(void* info)
96 RemoteInspectorDebuggableConnection *debuggableConnection = static_cast<RemoteInspectorDebuggableConnection*>(info);
98 RemoteInspectorQueue queueCopy;
100 std::lock_guard<std::mutex> lock(debuggableConnection->queueMutex());
101 queueCopy = debuggableConnection->queue();
102 debuggableConnection->clearQueue();
105 for (const auto& block : queueCopy)
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())
120 RemoteInspectorDebuggableConnection::~RemoteInspectorDebuggableConnection()
125 NSString *RemoteInspectorDebuggableConnection::destination() const
127 return [[m_destination copy] autorelease];
130 NSString *RemoteInspectorDebuggableConnection::connectionIdentifier() const
132 return [[m_connectionIdentifier copy] autorelease];
135 void RemoteInspectorDebuggableConnection::dispatchAsyncOnDebuggable(void (^block)())
138 queueTaskOnPrivateRunLoop(block);
143 if (WebCoreWebThreadIsEnabled && WebCoreWebThreadIsEnabled()) {
144 WebCoreWebThreadRun(block);
149 RemoteInspectorQueueTaskOnGlobalQueue(block);
152 bool RemoteInspectorDebuggableConnection::setup()
154 std::lock_guard<std::mutex> lock(m_debuggableMutex);
160 dispatchAsyncOnDebuggable(^{
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;
167 m_debuggable->connect(this);
177 void RemoteInspectorDebuggableConnection::closeFromDebuggable()
179 std::lock_guard<std::mutex> lock(m_debuggableMutex);
181 m_debuggable = nullptr;
184 void RemoteInspectorDebuggableConnection::close()
187 dispatchAsyncOnDebuggable(^{
189 std::lock_guard<std::mutex> lock(m_debuggableMutex);
193 m_debuggable->disconnect();
195 m_debuggable = nullptr;
202 void RemoteInspectorDebuggableConnection::sendMessageToBackend(NSString *message)
205 dispatchAsyncOnDebuggable(^{
207 RemoteInspectorDebuggable* debuggable = nullptr;
209 std::lock_guard<std::mutex> lock(m_debuggableMutex);
212 debuggable = m_debuggable;
215 debuggable->dispatchMessageFromRemoteFrontend(message);
221 bool RemoteInspectorDebuggableConnection::sendMessageToFrontend(const String& message)
223 RemoteInspector::shared().sendMessageToRemoteFrontend(identifier(), message);
228 void RemoteInspectorDebuggableConnection::setupRunLoop()
230 CFRunLoopRef debuggerRunLoop = m_debuggable->debuggerRunLoop();
231 if (!debuggerRunLoop) {
232 RemoteInspectorInitializeGlobalQueue();
236 m_runLoop = debuggerRunLoop;
238 CFRunLoopSourceContext runLoopSourceContext = {0, this, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, RemoteInspectorHandleRunSourceWithInfo};
239 m_runLoopSource = CFRunLoopSourceCreate(nullptr, 1, &runLoopSourceContext);
241 CFRunLoopAddSource(m_runLoop.get(), m_runLoopSource.get(), kCFRunLoopDefaultMode);
242 CFRunLoopAddSource(m_runLoop.get(), m_runLoopSource.get(), EventLoop::remoteInspectorRunLoopMode());
245 void RemoteInspectorDebuggableConnection::teardownRunLoop()
250 CFRunLoopRemoveSource(m_runLoop.get(), m_runLoopSource.get(), kCFRunLoopDefaultMode);
251 CFRunLoopRemoveSource(m_runLoop.get(), m_runLoopSource.get(), EventLoop::remoteInspectorRunLoopMode());
254 m_runLoopSource = nullptr;
257 void RemoteInspectorDebuggableConnection::queueTaskOnPrivateRunLoop(void (^block)())
262 std::lock_guard<std::mutex> lock(m_queueMutex);
263 m_queue.append(RemoteInspectorBlock(block));
266 CFRunLoopSourceSignal(m_runLoopSource.get());
267 CFRunLoopWakeUp(m_runLoop.get());
270 } // namespace Inspector
272 #endif // ENABLE(REMOTE_INSPECTOR)