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#ifndef WorkerThreadableWebSocketChannel_h 32#define WorkerThreadableWebSocketChannel_h 33 34#if ENABLE(WEB_SOCKETS) 35 36#include "ThreadableWebSocketChannel.h" 37#include "WebSocketChannelClient.h" 38#include "WorkerGlobalScope.h" 39 40#include <wtf/PassRefPtr.h> 41#include <wtf/RefCounted.h> 42#include <wtf/RefPtr.h> 43#include <wtf/Threading.h> 44#include <wtf/text/WTFString.h> 45 46namespace WebCore { 47 48class URL; 49class ScriptExecutionContext; 50class ThreadableWebSocketChannelClientWrapper; 51class WorkerGlobalScope; 52class WorkerLoaderProxy; 53class WorkerRunLoop; 54 55class WorkerThreadableWebSocketChannel : public RefCounted<WorkerThreadableWebSocketChannel>, public ThreadableWebSocketChannel { 56 WTF_MAKE_FAST_ALLOCATED; 57public: 58 static PassRefPtr<ThreadableWebSocketChannel> create(WorkerGlobalScope* workerGlobalScope, WebSocketChannelClient* client, const String& taskMode) 59 { 60 return adoptRef(new WorkerThreadableWebSocketChannel(workerGlobalScope, client, taskMode)); 61 } 62 virtual ~WorkerThreadableWebSocketChannel(); 63 64 // ThreadableWebSocketChannel functions. 65 virtual void connect(const URL&, const String& protocol) override; 66 virtual String subprotocol() override; 67 virtual String extensions() override; 68 virtual ThreadableWebSocketChannel::SendResult send(const String& message) override; 69 virtual ThreadableWebSocketChannel::SendResult send(const JSC::ArrayBuffer&, unsigned byteOffset, unsigned byteLength) override; 70 virtual ThreadableWebSocketChannel::SendResult send(Blob&) override; 71 virtual unsigned long bufferedAmount() const override; 72 virtual void close(int code, const String& reason) override; 73 virtual void fail(const String& reason) override; 74 virtual void disconnect() override; // Will suppress didClose(). 75 virtual void suspend() override; 76 virtual void resume() override; 77 78 // Generated by the bridge. The Peer and its bridge should have identical 79 // lifetimes. 80 class Peer : public WebSocketChannelClient { 81 WTF_MAKE_NONCOPYABLE(Peer); WTF_MAKE_FAST_ALLOCATED; 82 public: 83 static Peer* create(PassRefPtr<ThreadableWebSocketChannelClientWrapper> clientWrapper, WorkerLoaderProxy& loaderProxy, ScriptExecutionContext* context, const String& taskMode) 84 { 85 return new Peer(clientWrapper, loaderProxy, context, taskMode); 86 } 87 ~Peer(); 88 89 void connect(const URL&, const String& protocol); 90 void send(const String& message); 91 void send(const JSC::ArrayBuffer&); 92 void send(Blob&); 93 void bufferedAmount(); 94 void close(int code, const String& reason); 95 void fail(const String& reason); 96 void disconnect(); 97 void suspend(); 98 void resume(); 99 100 // WebSocketChannelClient functions. 101 virtual void didConnect() override; 102 virtual void didReceiveMessage(const String& message) override; 103 virtual void didReceiveBinaryData(PassOwnPtr<Vector<char>>) override; 104 virtual void didUpdateBufferedAmount(unsigned long bufferedAmount) override; 105 virtual void didStartClosingHandshake() override; 106 virtual void didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus, unsigned short code, const String& reason) override; 107 virtual void didReceiveMessageError() override; 108 109 private: 110 Peer(PassRefPtr<ThreadableWebSocketChannelClientWrapper>, WorkerLoaderProxy&, ScriptExecutionContext*, const String& taskMode); 111 112 RefPtr<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; 113 WorkerLoaderProxy& m_loaderProxy; 114 RefPtr<ThreadableWebSocketChannel> m_mainWebSocketChannel; 115 String m_taskMode; 116 }; 117 118 using RefCounted<WorkerThreadableWebSocketChannel>::ref; 119 using RefCounted<WorkerThreadableWebSocketChannel>::deref; 120 121protected: 122 virtual void refThreadableWebSocketChannel() { ref(); } 123 virtual void derefThreadableWebSocketChannel() { deref(); } 124 125private: 126 // Bridge for Peer. Running on the worker thread. 127 class Bridge : public RefCounted<Bridge> { 128 public: 129 static PassRefPtr<Bridge> create(PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, PassRefPtr<WorkerGlobalScope> workerGlobalScope, const String& taskMode) 130 { 131 return adoptRef(new Bridge(workerClientWrapper, workerGlobalScope, taskMode)); 132 } 133 ~Bridge(); 134 void initialize(); 135 void connect(const URL&, const String& protocol); 136 ThreadableWebSocketChannel::SendResult send(const String& message); 137 ThreadableWebSocketChannel::SendResult send(const JSC::ArrayBuffer&, unsigned byteOffset, unsigned byteLength); 138 ThreadableWebSocketChannel::SendResult send(Blob&); 139 unsigned long bufferedAmount(); 140 void close(int code, const String& reason); 141 void fail(const String& reason); 142 void disconnect(); 143 void suspend(); 144 void resume(); 145 146 using RefCounted<Bridge>::ref; 147 using RefCounted<Bridge>::deref; 148 149 private: 150 Bridge(PassRefPtr<ThreadableWebSocketChannelClientWrapper>, PassRefPtr<WorkerGlobalScope>, const String& taskMode); 151 152 static void setWebSocketChannel(ScriptExecutionContext*, Bridge* thisPtr, Peer*, PassRefPtr<ThreadableWebSocketChannelClientWrapper>); 153 154 // Executed on the main thread to create a Peer for this bridge. 155 static void mainThreadInitialize(ScriptExecutionContext&, WorkerLoaderProxy*, PassRefPtr<ThreadableWebSocketChannelClientWrapper>, const String& taskMode); 156 157 // Executed on the worker context's thread. 158 void clearClientWrapper(); 159 160 void setMethodNotCompleted(); 161 void waitForMethodCompletion(); 162 163 RefPtr<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; 164 RefPtr<WorkerGlobalScope> m_workerGlobalScope; 165 WorkerLoaderProxy& m_loaderProxy; 166 String m_taskMode; 167 Peer* m_peer; 168 }; 169 170 WorkerThreadableWebSocketChannel(WorkerGlobalScope*, WebSocketChannelClient*, const String& taskMode); 171 172 static void mainThreadConnect(ScriptExecutionContext&, Peer*, const URL&, const String& protocol); 173 static void mainThreadSend(ScriptExecutionContext&, Peer*, const String& message); 174 static void mainThreadSendArrayBuffer(ScriptExecutionContext&, Peer*, PassOwnPtr<Vector<char>>); 175 static void mainThreadSendBlob(ScriptExecutionContext&, Peer*, const URL&, const String& type, long long size); 176 static void mainThreadBufferedAmount(ScriptExecutionContext&, Peer*); 177 static void mainThreadClose(ScriptExecutionContext&, Peer*, int code, const String& reason); 178 static void mainThreadFail(ScriptExecutionContext&, Peer*, const String& reason); 179 static void mainThreadDestroy(ScriptExecutionContext&, Peer*); 180 static void mainThreadSuspend(ScriptExecutionContext&, Peer*); 181 static void mainThreadResume(ScriptExecutionContext&, Peer*); 182 183 class WorkerGlobalScopeDidInitializeTask; 184 185 RefPtr<WorkerGlobalScope> m_workerGlobalScope; 186 RefPtr<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; 187 RefPtr<Bridge> m_bridge; 188}; 189 190} // namespace WebCore 191 192#endif // ENABLE(WEB_SOCKETS) 193 194#endif // WorkerThreadableWebSocketChannel_h 195