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 <dispatch/dispatch.h>
34 #import <wtf/Vector.h>
37 #import <wtf/ios/WebCoreThread.h>
42 static std::mutex* rwiQueueMutex;
43 static CFRunLoopSourceRef rwiRunLoopSource;
44 static RemoteInspectorQueue* rwiQueue;
46 static void RemoteInspectorHandleRunSourceGlobal(void*)
48 ASSERT(CFRunLoopGetCurrent() == CFRunLoopGetMain());
49 ASSERT(rwiQueueMutex);
50 ASSERT(rwiRunLoopSource);
53 RemoteInspectorQueue queueCopy;
55 std::lock_guard<std::mutex> lock(*rwiQueueMutex);
56 queueCopy = *rwiQueue;
60 for (const auto& block : queueCopy)
64 static void RemoteInspectorQueueTaskOnGlobalQueue(void (^task)())
66 ASSERT(rwiQueueMutex);
67 ASSERT(rwiRunLoopSource);
71 std::lock_guard<std::mutex> lock(*rwiQueueMutex);
72 rwiQueue->append(RemoteInspectorBlock(task));
75 CFRunLoopSourceSignal(rwiRunLoopSource);
76 CFRunLoopWakeUp(CFRunLoopGetMain());
79 static void RemoteInspectorInitializeGlobalQueue()
81 static dispatch_once_t pred;
82 dispatch_once(&pred, ^{
83 rwiQueue = new RemoteInspectorQueue;
84 rwiQueueMutex = std::make_unique<std::mutex>().release();
86 CFRunLoopSourceContext runLoopSourceContext = {0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, RemoteInspectorHandleRunSourceGlobal};
87 rwiRunLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 1, &runLoopSourceContext);
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());
95 static void RemoteInspectorHandleRunSourceWithInfo(void* info)
97 RemoteInspectorDebuggableConnection *debuggableConnection = static_cast<RemoteInspectorDebuggableConnection*>(info);
99 RemoteInspectorQueue queueCopy;
101 std::lock_guard<std::mutex> lock(debuggableConnection->queueMutex());
102 queueCopy = debuggableConnection->queue();
103 debuggableConnection->clearQueue();
106 for (const auto& block : queueCopy)
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())
121 RemoteInspectorDebuggableConnection::~RemoteInspectorDebuggableConnection()
126 NSString *RemoteInspectorDebuggableConnection::destination() const
128 return [[m_destination copy] autorelease];
131 NSString *RemoteInspectorDebuggableConnection::connectionIdentifier() const
133 return [[m_connectionIdentifier copy] autorelease];
136 void RemoteInspectorDebuggableConnection::dispatchAsyncOnDebuggable(void (^block)())
139 queueTaskOnPrivateRunLoop(block);
144 if (WebCoreWebThreadIsEnabled && WebCoreWebThreadIsEnabled()) {
145 WebCoreWebThreadRun(block);
150 RemoteInspectorQueueTaskOnGlobalQueue(block);
153 bool RemoteInspectorDebuggableConnection::setup(bool isAutomaticInspection, bool automaticallyPause)
155 std::lock_guard<std::mutex> lock(m_debuggableMutex);
161 dispatchAsyncOnDebuggable(^{
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;
168 m_debuggable->connect(this, isAutomaticInspection);
171 if (automaticallyPause)
172 m_debuggable->pause();
181 void RemoteInspectorDebuggableConnection::closeFromDebuggable()
183 std::lock_guard<std::mutex> lock(m_debuggableMutex);
185 m_debuggable = nullptr;
188 void RemoteInspectorDebuggableConnection::close()
191 dispatchAsyncOnDebuggable(^{
193 std::lock_guard<std::mutex> lock(m_debuggableMutex);
197 m_debuggable->disconnect();
199 m_debuggable = nullptr;
206 void RemoteInspectorDebuggableConnection::sendMessageToBackend(NSString *message)
209 dispatchAsyncOnDebuggable(^{
211 RemoteInspectorDebuggable* debuggable = nullptr;
213 std::lock_guard<std::mutex> lock(m_debuggableMutex);
216 debuggable = m_debuggable;
219 debuggable->dispatchMessageFromRemoteFrontend(message);
225 bool RemoteInspectorDebuggableConnection::sendMessageToFrontend(const String& message)
227 RemoteInspector::singleton().sendMessageToRemoteFrontend(identifier(), message);
232 void RemoteInspectorDebuggableConnection::setupRunLoop()
234 CFRunLoopRef debuggerRunLoop = m_debuggable->debuggerRunLoop();
235 if (!debuggerRunLoop) {
236 RemoteInspectorInitializeGlobalQueue();
240 m_runLoop = debuggerRunLoop;
242 CFRunLoopSourceContext runLoopSourceContext = {0, this, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, RemoteInspectorHandleRunSourceWithInfo};
243 m_runLoopSource = adoptCF(CFRunLoopSourceCreate(kCFAllocatorDefault, 1, &runLoopSourceContext));
245 CFRunLoopAddSource(m_runLoop.get(), m_runLoopSource.get(), kCFRunLoopDefaultMode);
246 CFRunLoopAddSource(m_runLoop.get(), m_runLoopSource.get(), EventLoop::remoteInspectorRunLoopMode());
249 void RemoteInspectorDebuggableConnection::teardownRunLoop()
254 CFRunLoopRemoveSource(m_runLoop.get(), m_runLoopSource.get(), kCFRunLoopDefaultMode);
255 CFRunLoopRemoveSource(m_runLoop.get(), m_runLoopSource.get(), EventLoop::remoteInspectorRunLoopMode());
258 m_runLoopSource = nullptr;
261 void RemoteInspectorDebuggableConnection::queueTaskOnPrivateRunLoop(void (^block)())
266 std::lock_guard<std::mutex> lock(m_queueMutex);
267 m_queue.append(RemoteInspectorBlock(block));
270 CFRunLoopSourceSignal(m_runLoopSource.get());
271 CFRunLoopWakeUp(m_runLoop.get());
274 } // namespace Inspector
276 #endif // ENABLE(REMOTE_INSPECTOR)