Use Optional::valueOr() instead of Optional::value_or()
[WebKit-https.git] / Source / JavaScriptCore / inspector / remote / cocoa / RemoteConnectionToTargetCocoa.mm
1 /*
2  * Copyright (C) 2013, 2015 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 "RemoteConnectionToTarget.h"
28
29 #if ENABLE(REMOTE_INSPECTOR)
30
31 #import "EventLoop.h"
32 #import "RemoteAutomationTarget.h"
33 #import "RemoteInspectionTarget.h"
34 #import "RemoteInspector.h"
35 #import <dispatch/dispatch.h>
36 #import <wtf/Optional.h>
37
38 #if PLATFORM(IOS_FAMILY)
39 #import <wtf/ios/WebCoreThread.h>
40 #endif
41
42 namespace Inspector {
43
44 static Lock rwiQueueMutex;
45 static CFRunLoopSourceRef rwiRunLoopSource;
46 static RemoteTargetQueue* rwiQueue;
47
48 static void RemoteTargetHandleRunSourceGlobal(void*)
49 {
50     ASSERT(CFRunLoopGetCurrent() == CFRunLoopGetMain());
51     ASSERT(rwiRunLoopSource);
52     ASSERT(rwiQueue);
53
54     RemoteTargetQueue queueCopy;
55     {
56         std::lock_guard<Lock> lock(rwiQueueMutex);
57         queueCopy = *rwiQueue;
58         rwiQueue->clear();
59     }
60
61     for (const auto& block : queueCopy)
62         block();
63 }
64
65 static void RemoteTargetQueueTaskOnGlobalQueue(void (^task)())
66 {
67     ASSERT(rwiRunLoopSource);
68     ASSERT(rwiQueue);
69
70     {
71         std::lock_guard<Lock> lock(rwiQueueMutex);
72         rwiQueue->append(task);
73     }
74
75     CFRunLoopSourceSignal(rwiRunLoopSource);
76     CFRunLoopWakeUp(CFRunLoopGetMain());
77 }
78
79 static void RemoteTargetInitializeGlobalQueue()
80 {
81     static dispatch_once_t pred;
82     dispatch_once(&pred, ^{
83         rwiQueue = new RemoteTargetQueue;
84
85         CFRunLoopSourceContext runLoopSourceContext = { 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, RemoteTargetHandleRunSourceGlobal };
86         rwiRunLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 1, &runLoopSourceContext);
87
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());
91     });
92 }
93
94 static void RemoteTargetHandleRunSourceWithInfo(void* info)
95 {
96     RemoteConnectionToTarget *connectionToTarget = static_cast<RemoteConnectionToTarget*>(info);
97
98     RemoteTargetQueue queueCopy;
99     {
100         std::lock_guard<Lock> lock(connectionToTarget->queueMutex());
101         queueCopy = connectionToTarget->queue();
102         connectionToTarget->clearQueue();
103     }
104
105     for (const auto& block : queueCopy)
106         block();
107 }
108
109
110 RemoteConnectionToTarget::RemoteConnectionToTarget(RemoteControllableTarget* target, NSString *connectionIdentifier, NSString *destination)
111     : m_target(target)
112     , m_connectionIdentifier(connectionIdentifier)
113     , m_destination(destination)
114 {
115     setupRunLoop();
116 }
117
118 RemoteConnectionToTarget::~RemoteConnectionToTarget()
119 {
120     teardownRunLoop();
121 }
122
123 Optional<unsigned> RemoteConnectionToTarget::targetIdentifier() const
124 {
125     return m_target ? Optional<unsigned>(m_target->targetIdentifier()) : WTF::nullopt;
126 }
127
128 NSString *RemoteConnectionToTarget::connectionIdentifier() const
129 {
130     return [[m_connectionIdentifier copy] autorelease];
131 }
132
133 NSString *RemoteConnectionToTarget::destination() const
134 {
135     return [[m_destination copy] autorelease];
136 }
137
138 void RemoteConnectionToTarget::dispatchAsyncOnTarget(void (^block)())
139 {
140     if (m_runLoop) {
141         queueTaskOnPrivateRunLoop(block);
142         return;
143     }
144
145 #if PLATFORM(IOS_FAMILY)
146     if (WebCoreWebThreadIsEnabled && WebCoreWebThreadIsEnabled()) {
147         WebCoreWebThreadRun(block);
148         return;
149     }
150 #endif
151
152     RemoteTargetQueueTaskOnGlobalQueue(block);
153 }
154
155 bool RemoteConnectionToTarget::setup(bool isAutomaticInspection, bool automaticallyPause)
156 {
157     std::lock_guard<Lock> lock(m_targetMutex);
158
159     if (!m_target)
160         return false;
161
162     unsigned targetIdentifier = this->targetIdentifier().valueOr(0);
163     
164     ref();
165     dispatchAsyncOnTarget(^{
166         {
167             std::lock_guard<Lock> lock(m_targetMutex);
168
169             if (!m_target || !m_target->remoteControlAllowed()) {
170                 RemoteInspector::singleton().setupFailed(targetIdentifier);
171                 m_target = nullptr;
172             } else if (is<RemoteInspectionTarget>(m_target)) {
173                 auto castedTarget = downcast<RemoteInspectionTarget>(m_target);
174                 castedTarget->connect(*this, isAutomaticInspection, automaticallyPause);
175                 m_connected = true;
176
177                 RemoteInspector::singleton().updateTargetListing(targetIdentifier);
178             } else if (is<RemoteAutomationTarget>(m_target)) {
179                 auto castedTarget = downcast<RemoteAutomationTarget>(m_target);
180                 castedTarget->connect(*this);
181                 m_connected = true;
182
183                 RemoteInspector::singleton().updateTargetListing(targetIdentifier);
184             }
185         }
186         deref();
187     });
188
189     return true;
190 }
191
192 void RemoteConnectionToTarget::targetClosed()
193 {
194     std::lock_guard<Lock> lock(m_targetMutex);
195
196     m_target = nullptr;
197 }
198
199 void RemoteConnectionToTarget::close()
200 {
201     unsigned targetIdentifier = m_target ? m_target->targetIdentifier() : 0;
202     
203     ref();
204     dispatchAsyncOnTarget(^{
205         {
206             std::lock_guard<Lock> lock(m_targetMutex);
207             if (m_target) {
208                 if (m_connected)
209                     m_target->disconnect(*this);
210
211                 m_target = nullptr;
212                 
213                 RemoteInspector::singleton().updateTargetListing(targetIdentifier);
214             }
215         }
216         deref();
217     });
218 }
219
220 void RemoteConnectionToTarget::sendMessageToTarget(NSString *message)
221 {
222     ref();
223     dispatchAsyncOnTarget(^{
224         {
225             RemoteControllableTarget* target = nullptr;
226             {
227                 std::lock_guard<Lock> lock(m_targetMutex);
228                 if (!m_target)
229                     return;
230                 target = m_target;
231             }
232
233             target->dispatchMessageFromRemote(message);
234         }
235         deref();
236     });
237 }
238
239 void RemoteConnectionToTarget::sendMessageToFrontend(const String& message)
240 {
241     if (!targetIdentifier())
242         return;
243
244     RemoteInspector::singleton().sendMessageToRemote(targetIdentifier().value(), message);
245 }
246
247 void RemoteConnectionToTarget::setupRunLoop()
248 {
249     CFRunLoopRef targetRunLoop = m_target->targetRunLoop();
250     if (!targetRunLoop) {
251         RemoteTargetInitializeGlobalQueue();
252         return;
253     }
254
255     m_runLoop = targetRunLoop;
256
257     CFRunLoopSourceContext runLoopSourceContext = { 0, this, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, RemoteTargetHandleRunSourceWithInfo };
258     m_runLoopSource = adoptCF(CFRunLoopSourceCreate(kCFAllocatorDefault, 1, &runLoopSourceContext));
259
260     CFRunLoopAddSource(m_runLoop.get(), m_runLoopSource.get(), kCFRunLoopDefaultMode);
261     CFRunLoopAddSource(m_runLoop.get(), m_runLoopSource.get(), EventLoop::remoteInspectorRunLoopMode());
262 }
263
264 void RemoteConnectionToTarget::teardownRunLoop()
265 {
266     if (!m_runLoop)
267         return;
268
269     CFRunLoopRemoveSource(m_runLoop.get(), m_runLoopSource.get(), kCFRunLoopDefaultMode);
270     CFRunLoopRemoveSource(m_runLoop.get(), m_runLoopSource.get(), EventLoop::remoteInspectorRunLoopMode());
271
272     m_runLoop = nullptr;
273     m_runLoopSource = nullptr;
274 }
275
276 void RemoteConnectionToTarget::queueTaskOnPrivateRunLoop(void (^block)())
277 {
278     ASSERT(m_runLoop);
279
280     {
281         std::lock_guard<Lock> lock(m_queueMutex);
282         m_queue.append(block);
283     }
284
285     CFRunLoopSourceSignal(m_runLoopSource.get());
286     CFRunLoopWakeUp(m_runLoop.get());
287 }
288
289 } // namespace Inspector
290
291 #endif // ENABLE(REMOTE_INSPECTOR)