ThreadableWebSocketChannelClientWrapper.cpp 10.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/*
 * Copyright (C) 2011 Google Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
32
#if ENABLE(WEB_SOCKETS)
33 34
#include "ThreadableWebSocketChannelClientWrapper.h"

35 36
#include "CrossThreadCopier.h"
#include "CrossThreadTask.h"
37
#include "ScriptExecutionContext.h"
38 39
#include "WebSocketChannelClient.h"
#include <wtf/PassRefPtr.h>
40
#include <wtf/RefPtr.h>
41 42 43

namespace WebCore {

44 45 46
ThreadableWebSocketChannelClientWrapper::ThreadableWebSocketChannelClientWrapper(ScriptExecutionContext* context, WebSocketChannelClient* client)
    : m_context(context)
    , m_client(client)
47
    , m_peer(0)
48
    , m_failedWebSocketChannelCreation(false)
49
    , m_syncMethodDone(true)
50
    , m_sendRequestResult(ThreadableWebSocketChannel::SendFail)
51 52 53 54 55
    , m_bufferedAmount(0)
    , m_suspended(false)
{
}

56
PassRefPtr<ThreadableWebSocketChannelClientWrapper> ThreadableWebSocketChannelClientWrapper::create(ScriptExecutionContext* context, WebSocketChannelClient* client)
57
{
58
    return adoptRef(new ThreadableWebSocketChannelClientWrapper(context, client));
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
}

void ThreadableWebSocketChannelClientWrapper::clearSyncMethodDone()
{
    m_syncMethodDone = false;
}

void ThreadableWebSocketChannelClientWrapper::setSyncMethodDone()
{
    m_syncMethodDone = true;
}

bool ThreadableWebSocketChannelClientWrapper::syncMethodDone() const
{
    return m_syncMethodDone;
}

76
WorkerThreadableWebSocketChannel::Peer* ThreadableWebSocketChannelClientWrapper::peer() const
77
{
78
    return m_peer;
79 80
}

81
void ThreadableWebSocketChannelClientWrapper::didCreateWebSocketChannel(WorkerThreadableWebSocketChannel::Peer* peer)
82
{
83 84 85 86 87 88 89 90 91
    m_peer = peer;
    m_syncMethodDone = true;
}

void ThreadableWebSocketChannelClientWrapper::clearPeer()
{
    m_peer = 0;
}

92 93 94 95 96 97 98 99 100 101
bool ThreadableWebSocketChannelClientWrapper::failedWebSocketChannelCreation() const
{
    return m_failedWebSocketChannelCreation;
}

void ThreadableWebSocketChannelClientWrapper::setFailedWebSocketChannelCreation()
{
    m_failedWebSocketChannelCreation = true;
}

102 103
String ThreadableWebSocketChannelClientWrapper::subprotocol() const
{
104
    if (m_subprotocol.isEmpty())
105
        return emptyString();
106
    return String(m_subprotocol);
107 108 109 110
}

void ThreadableWebSocketChannelClientWrapper::setSubprotocol(const String& subprotocol)
{
111 112 113 114
    unsigned length = subprotocol.length();
    m_subprotocol.resize(length);
    if (length)
        memcpy(m_subprotocol.data(), subprotocol.characters(), sizeof(UChar) * length);
115 116
}

117 118 119
String ThreadableWebSocketChannelClientWrapper::extensions() const
{
    if (m_extensions.isEmpty())
120
        return emptyString();
121 122 123 124 125 126 127 128 129 130 131
    return String(m_extensions);
}

void ThreadableWebSocketChannelClientWrapper::setExtensions(const String& extensions)
{
    unsigned length = extensions.length();
    m_extensions.resize(length);
    if (length)
        memcpy(m_extensions.data(), extensions.characters(), sizeof(UChar) * length);
}

132
ThreadableWebSocketChannel::SendResult ThreadableWebSocketChannelClientWrapper::sendRequestResult() const
133
{
134
    return m_sendRequestResult;
135 136
}

137
void ThreadableWebSocketChannelClientWrapper::setSendRequestResult(ThreadableWebSocketChannel::SendResult sendRequestResult)
138
{
139
    m_sendRequestResult = sendRequestResult;
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
    m_syncMethodDone = true;
}

unsigned long ThreadableWebSocketChannelClientWrapper::bufferedAmount() const
{
    return m_bufferedAmount;
}

void ThreadableWebSocketChannelClientWrapper::setBufferedAmount(unsigned long bufferedAmount)
{
    m_bufferedAmount = bufferedAmount;
    m_syncMethodDone = true;
}

void ThreadableWebSocketChannelClientWrapper::clearClient()
{
    m_client = 0;
}

void ThreadableWebSocketChannelClientWrapper::didConnect()
{
161
    m_pendingTasks.append(createCallbackTask(&didConnectCallback, this));
162
    if (!m_suspended)
163
        processPendingTasks();
164 165 166 167
}

void ThreadableWebSocketChannelClientWrapper::didReceiveMessage(const String& message)
{
168
    m_pendingTasks.append(createCallbackTask(&didReceiveMessageCallback, this, message));
169
    if (!m_suspended)
170
        processPendingTasks();
171 172
}

173
void ThreadableWebSocketChannelClientWrapper::didReceiveBinaryData(PassOwnPtr<Vector<char>> binaryData)
174
{
175
    m_pendingTasks.append(createCallbackTask(&didReceiveBinaryDataCallback, this, binaryData));
176 177 178 179
    if (!m_suspended)
        processPendingTasks();
}

180 181
void ThreadableWebSocketChannelClientWrapper::didUpdateBufferedAmount(unsigned long bufferedAmount)
{
182
    m_pendingTasks.append(createCallbackTask(&didUpdateBufferedAmountCallback, this, bufferedAmount));
183 184 185 186
    if (!m_suspended)
        processPendingTasks();
}

187
void ThreadableWebSocketChannelClientWrapper::didStartClosingHandshake()
188
{
189
    m_pendingTasks.append(createCallbackTask(&didStartClosingHandshakeCallback, this));
190 191 192 193
    if (!m_suspended)
        processPendingTasks();
}

194
void ThreadableWebSocketChannelClientWrapper::didClose(unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason)
195
{
196
    m_pendingTasks.append(createCallbackTask(&didCloseCallback, this, unhandledBufferedAmount, closingHandshakeCompletion, code, reason));
197
    if (!m_suspended)
198
        processPendingTasks();
199 200
}

201 202 203 204 205 206 207
void ThreadableWebSocketChannelClientWrapper::didReceiveMessageError()
{
    m_pendingTasks.append(createCallbackTask(&didReceiveMessageErrorCallback, this));
    if (!m_suspended)
        processPendingTasks();
}

208 209 210 211 212 213 214 215
void ThreadableWebSocketChannelClientWrapper::suspend()
{
    m_suspended = true;
}

void ThreadableWebSocketChannelClientWrapper::resume()
{
    m_suspended = false;
216
    processPendingTasks();
217 218
}

219 220
void ThreadableWebSocketChannelClientWrapper::processPendingTasksCallback(ScriptExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper)
{
221
    ASSERT_UNUSED(context, context->isWorkerGlobalScope());
222 223 224
    wrapper->processPendingTasks();
}

225
void ThreadableWebSocketChannelClientWrapper::processPendingTasks()
226
{
227 228 229 230 231 232 233 234
    if (m_suspended)
        return;
    if (!m_syncMethodDone) {
        // When a synchronous operation is in progress (i.e. the execution stack contains
        // WorkerThreadableWebSocketChannel::waitForMethodCompletion()), we cannot invoke callbacks in this run loop.
        m_context->postTask(createCallbackTask(&ThreadableWebSocketChannelClientWrapper::processPendingTasksCallback, this));
        return;
    }
235
    Vector<OwnPtr<ScriptExecutionContext::Task>> tasks;
236
    tasks.swap(m_pendingTasks);
237
    for (Vector<OwnPtr<ScriptExecutionContext::Task>>::const_iterator iter = tasks.begin(); iter != tasks.end(); ++iter)
238 239 240
        (*iter)->performTask(0);
}

241
void ThreadableWebSocketChannelClientWrapper::didConnectCallback(ScriptExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper)
242 243 244 245 246 247
{
    ASSERT_UNUSED(context, !context);
    if (wrapper->m_client)
        wrapper->m_client->didConnect();
}

248
void ThreadableWebSocketChannelClientWrapper::didReceiveMessageCallback(ScriptExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper, const String& message)
249 250 251 252 253 254
{
    ASSERT_UNUSED(context, !context);
    if (wrapper->m_client)
        wrapper->m_client->didReceiveMessage(message);
}

255
void ThreadableWebSocketChannelClientWrapper::didReceiveBinaryDataCallback(ScriptExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper, PassOwnPtr<Vector<char>> binaryData)
256 257 258 259 260 261
{
    ASSERT_UNUSED(context, !context);
    if (wrapper->m_client)
        wrapper->m_client->didReceiveBinaryData(binaryData);
}

262
void ThreadableWebSocketChannelClientWrapper::didUpdateBufferedAmountCallback(ScriptExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper, unsigned long bufferedAmount)
263 264 265 266 267 268
{
    ASSERT_UNUSED(context, !context);
    if (wrapper->m_client)
        wrapper->m_client->didUpdateBufferedAmount(bufferedAmount);
}

269
void ThreadableWebSocketChannelClientWrapper::didStartClosingHandshakeCallback(ScriptExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper)
270 271 272 273 274 275
{
    ASSERT_UNUSED(context, !context);
    if (wrapper->m_client)
        wrapper->m_client->didStartClosingHandshake();
}

276
void ThreadableWebSocketChannelClientWrapper::didCloseCallback(ScriptExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper, unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason)
277 278 279
{
    ASSERT_UNUSED(context, !context);
    if (wrapper->m_client)
280
        wrapper->m_client->didClose(unhandledBufferedAmount, closingHandshakeCompletion, code, reason);
281 282
}

283 284 285 286 287 288 289
void ThreadableWebSocketChannelClientWrapper::didReceiveMessageErrorCallback(ScriptExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> wrapper)
{
    ASSERT_UNUSED(context, !context);
    if (wrapper->m_client)
        wrapper->m_client->didReceiveMessageError();
}

290 291 292
} // namespace WebCore

#endif