[WebGL] Add `--webgl-test-suite` flag for run-webkit-tests
[WebKit-https.git] / Source / WebCore / Modules / websockets / ThreadableWebSocketChannelClientWrapper.cpp
1 /*
2  * Copyright (C) 2011 Google 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "ThreadableWebSocketChannelClientWrapper.h"
33
34 #include "ScriptExecutionContext.h"
35 #include "WebSocketChannelClient.h"
36 #include <wtf/RefPtr.h>
37 #include <wtf/text/StringView.h>
38
39 namespace WebCore {
40
41 ThreadableWebSocketChannelClientWrapper::ThreadableWebSocketChannelClientWrapper(ScriptExecutionContext& context, WebSocketChannelClient& client)
42     : m_context(context)
43     , m_client(&client)
44     , m_peer(nullptr)
45     , m_failedWebSocketChannelCreation(false)
46     , m_syncMethodDone(true)
47     , m_sendRequestResult(ThreadableWebSocketChannel::SendFail)
48     , m_bufferedAmount(0)
49     , m_suspended(false)
50 {
51 }
52
53 Ref<ThreadableWebSocketChannelClientWrapper> ThreadableWebSocketChannelClientWrapper::create(ScriptExecutionContext& context, WebSocketChannelClient& client)
54 {
55     return adoptRef(*new ThreadableWebSocketChannelClientWrapper(context, client));
56 }
57
58 void ThreadableWebSocketChannelClientWrapper::clearSyncMethodDone()
59 {
60     m_syncMethodDone = false;
61 }
62
63 void ThreadableWebSocketChannelClientWrapper::setSyncMethodDone()
64 {
65     m_syncMethodDone = true;
66 }
67
68 bool ThreadableWebSocketChannelClientWrapper::syncMethodDone() const
69 {
70     return m_syncMethodDone;
71 }
72
73 WorkerThreadableWebSocketChannel::Peer* ThreadableWebSocketChannelClientWrapper::peer() const
74 {
75     return m_peer;
76 }
77
78 void ThreadableWebSocketChannelClientWrapper::didCreateWebSocketChannel(WorkerThreadableWebSocketChannel::Peer* peer)
79 {
80     m_peer = peer;
81     m_syncMethodDone = true;
82 }
83
84 void ThreadableWebSocketChannelClientWrapper::clearPeer()
85 {
86     m_peer = nullptr;
87 }
88
89 bool ThreadableWebSocketChannelClientWrapper::failedWebSocketChannelCreation() const
90 {
91     return m_failedWebSocketChannelCreation;
92 }
93
94 void ThreadableWebSocketChannelClientWrapper::setFailedWebSocketChannelCreation()
95 {
96     m_failedWebSocketChannelCreation = true;
97 }
98
99 String ThreadableWebSocketChannelClientWrapper::subprotocol() const
100 {
101     if (m_subprotocol.isEmpty())
102         return emptyString();
103     return String(m_subprotocol);
104 }
105
106 void ThreadableWebSocketChannelClientWrapper::setSubprotocol(const String& subprotocol)
107 {
108     unsigned length = subprotocol.length();
109     m_subprotocol.resize(length);
110     StringView(subprotocol).getCharactersWithUpconvert(m_subprotocol.data());
111 }
112
113 String ThreadableWebSocketChannelClientWrapper::extensions() const
114 {
115     if (m_extensions.isEmpty())
116         return emptyString();
117     return String(m_extensions);
118 }
119
120 void ThreadableWebSocketChannelClientWrapper::setExtensions(const String& extensions)
121 {
122     unsigned length = extensions.length();
123     m_extensions.resize(length);
124     StringView(extensions).getCharactersWithUpconvert(m_extensions.data());
125 }
126
127 ThreadableWebSocketChannel::SendResult ThreadableWebSocketChannelClientWrapper::sendRequestResult() const
128 {
129     return m_sendRequestResult;
130 }
131
132 void ThreadableWebSocketChannelClientWrapper::setSendRequestResult(ThreadableWebSocketChannel::SendResult sendRequestResult)
133 {
134     m_sendRequestResult = sendRequestResult;
135     m_syncMethodDone = true;
136 }
137
138 unsigned ThreadableWebSocketChannelClientWrapper::bufferedAmount() const
139 {
140     return m_bufferedAmount;
141 }
142
143 void ThreadableWebSocketChannelClientWrapper::setBufferedAmount(unsigned bufferedAmount)
144 {
145     m_bufferedAmount = bufferedAmount;
146     m_syncMethodDone = true;
147 }
148
149 void ThreadableWebSocketChannelClientWrapper::clearClient()
150 {
151     m_client = nullptr;
152 }
153
154 void ThreadableWebSocketChannelClientWrapper::didConnect()
155 {
156     m_pendingTasks.append(makeUnique<ScriptExecutionContext::Task>([this, protectedThis = makeRef(*this)] (ScriptExecutionContext&) {
157         if (m_client)
158             m_client->didConnect();
159     }));
160
161     if (!m_suspended)
162         processPendingTasks();
163 }
164
165 void ThreadableWebSocketChannelClientWrapper::didReceiveMessage(const String& message)
166 {
167     m_pendingTasks.append(makeUnique<ScriptExecutionContext::Task>([this, protectedThis = makeRef(*this), message = message.isolatedCopy()] (ScriptExecutionContext&) {
168         if (m_client)
169             m_client->didReceiveMessage(message);
170     }));
171
172     if (!m_suspended)
173         processPendingTasks();
174 }
175
176 void ThreadableWebSocketChannelClientWrapper::didReceiveBinaryData(Vector<uint8_t>&& binaryData)
177 {
178     m_pendingTasks.append(makeUnique<ScriptExecutionContext::Task>([this, protectedThis = makeRef(*this), binaryData = WTFMove(binaryData)] (ScriptExecutionContext&) mutable {
179         if (m_client)
180             m_client->didReceiveBinaryData(WTFMove(binaryData));
181     }));
182
183     if (!m_suspended)
184         processPendingTasks();
185 }
186
187 void ThreadableWebSocketChannelClientWrapper::didUpdateBufferedAmount(unsigned bufferedAmount)
188 {
189     m_pendingTasks.append(makeUnique<ScriptExecutionContext::Task>([this, protectedThis = makeRef(*this), bufferedAmount] (ScriptExecutionContext&) {
190         if (m_client)
191             m_client->didUpdateBufferedAmount(bufferedAmount);
192     }));
193
194     if (!m_suspended)
195         processPendingTasks();
196 }
197
198 void ThreadableWebSocketChannelClientWrapper::didStartClosingHandshake()
199 {
200     m_pendingTasks.append(makeUnique<ScriptExecutionContext::Task>([this, protectedThis = makeRef(*this)] (ScriptExecutionContext&) {
201         if (m_client)
202             m_client->didStartClosingHandshake();
203     }));
204
205     if (!m_suspended)
206         processPendingTasks();
207 }
208
209 void ThreadableWebSocketChannelClientWrapper::didClose(unsigned unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason)
210 {
211     m_pendingTasks.append(makeUnique<ScriptExecutionContext::Task>([this, protectedThis = makeRef(*this), unhandledBufferedAmount, closingHandshakeCompletion, code, reason = reason.isolatedCopy()] (ScriptExecutionContext&) {
212             if (m_client)
213                 m_client->didClose(unhandledBufferedAmount, closingHandshakeCompletion, code, reason);
214         }));
215
216     if (!m_suspended)
217         processPendingTasks();
218 }
219
220 void ThreadableWebSocketChannelClientWrapper::didReceiveMessageError()
221 {
222     m_pendingTasks.append(makeUnique<ScriptExecutionContext::Task>([this, protectedThis = makeRef(*this)] (ScriptExecutionContext&) {
223         if (m_client)
224             m_client->didReceiveMessageError();
225     }));
226
227     if (!m_suspended)
228         processPendingTasks();
229 }
230
231 void ThreadableWebSocketChannelClientWrapper::didUpgradeURL()
232 {
233     m_pendingTasks.append(makeUnique<ScriptExecutionContext::Task>([this, protectedThis = makeRef(*this)] (ScriptExecutionContext&) {
234         if (m_client)
235             m_client->didUpgradeURL();
236     }));
237     
238     if (!m_suspended)
239         processPendingTasks();
240 }
241
242 void ThreadableWebSocketChannelClientWrapper::suspend()
243 {
244     m_suspended = true;
245 }
246
247 void ThreadableWebSocketChannelClientWrapper::resume()
248 {
249     m_suspended = false;
250     processPendingTasks();
251 }
252
253 void ThreadableWebSocketChannelClientWrapper::processPendingTasks()
254 {
255     if (m_suspended)
256         return;
257     if (!m_syncMethodDone) {
258         // When a synchronous operation is in progress (i.e. the execution stack contains
259         // WorkerThreadableWebSocketChannel::waitForMethodCompletion()), we cannot invoke callbacks in this run loop.
260         m_context.postTask([this, protectedThis = makeRef(*this)] (ScriptExecutionContext& context) {
261             ASSERT_UNUSED(context, context.isWorkerGlobalScope());
262             processPendingTasks();
263         });
264         return;
265     }
266
267     Vector<std::unique_ptr<ScriptExecutionContext::Task>> pendingTasks = WTFMove(m_pendingTasks);
268     for (auto& task : pendingTasks)
269         task->performTask(m_context);
270 }
271
272 } // namespace WebCore