1 /* 2 * Copyright (C) 2009, 2010 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) && ENABLE(WORKERS) 35 36 #include "PlatformString.h" 37 #include "ThreadableWebSocketChannel.h" 38 #include "WebSocketChannelClient.h" 39 40 #include <wtf/PassRefPtr.h> 41 #include <wtf/RefCounted.h> 42 #include <wtf/RefPtr.h> 43 #include <wtf/Threading.h> 44 45 namespace WebCore { 46 47 class KURL; 48 class ScriptExecutionContext; 49 class ThreadableWebSocketChannelClientWrapper; 50 class WorkerContext; 51 class WorkerLoaderProxy; 52 class WorkerRunLoop; 53 54 class WorkerThreadableWebSocketChannel : public RefCounted<WorkerThreadableWebSocketChannel>, public ThreadableWebSocketChannel { 55 WTF_MAKE_FAST_ALLOCATED; 56 public: create(WorkerContext * workerContext,WebSocketChannelClient * client,const String & taskMode,const KURL & url,const String & protocol)57 static PassRefPtr<ThreadableWebSocketChannel> create(WorkerContext* workerContext, WebSocketChannelClient* client, const String& taskMode, const KURL& url, const String& protocol) 58 { 59 return adoptRef(new WorkerThreadableWebSocketChannel(workerContext, client, taskMode, url, protocol)); 60 } 61 virtual ~WorkerThreadableWebSocketChannel(); 62 63 virtual void connect(); 64 virtual bool send(const String& message); 65 virtual unsigned long bufferedAmount() const; 66 virtual void close(); 67 virtual void disconnect(); // Will suppress didClose(). 68 virtual void suspend(); 69 virtual void resume(); 70 71 using RefCounted<WorkerThreadableWebSocketChannel>::ref; 72 using RefCounted<WorkerThreadableWebSocketChannel>::deref; 73 74 protected: refThreadableWebSocketChannel()75 virtual void refThreadableWebSocketChannel() { ref(); } derefThreadableWebSocketChannel()76 virtual void derefThreadableWebSocketChannel() { deref(); } 77 78 private: 79 // Generated by the bridge. The Peer and its bridge should have identical 80 // lifetimes. 81 class Peer : public WebSocketChannelClient { 82 WTF_MAKE_NONCOPYABLE(Peer); WTF_MAKE_FAST_ALLOCATED; 83 public: create(RefPtr<ThreadableWebSocketChannelClientWrapper> clientWrapper,WorkerLoaderProxy & loaderProxy,ScriptExecutionContext * context,const String & taskMode,const KURL & url,const String & protocol)84 static Peer* create(RefPtr<ThreadableWebSocketChannelClientWrapper> clientWrapper, WorkerLoaderProxy& loaderProxy, ScriptExecutionContext* context, const String& taskMode, const KURL& url, const String& protocol) 85 { 86 return new Peer(clientWrapper, loaderProxy, context, taskMode, url, protocol); 87 } 88 ~Peer(); 89 90 void connect(); 91 void send(const String& message); 92 void bufferedAmount(); 93 void close(); 94 void disconnect(); 95 void suspend(); 96 void resume(); 97 98 virtual void didConnect(); 99 virtual void didReceiveMessage(const String& message); 100 virtual void didClose(unsigned long unhandledBufferedAmount); 101 102 private: 103 Peer(RefPtr<ThreadableWebSocketChannelClientWrapper>, WorkerLoaderProxy&, ScriptExecutionContext*, const String& taskMode, const KURL&, const String& protocol); 104 105 RefPtr<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; 106 WorkerLoaderProxy& m_loaderProxy; 107 RefPtr<ThreadableWebSocketChannel> m_mainWebSocketChannel; 108 String m_taskMode; 109 }; 110 111 // Bridge for Peer. Running on the worker thread. 112 class Bridge : public RefCounted<Bridge> { 113 public: create(PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper,PassRefPtr<WorkerContext> workerContext,const String & taskMode,const KURL & url,const String & protocol)114 static PassRefPtr<Bridge> create(PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, PassRefPtr<WorkerContext> workerContext, const String& taskMode, const KURL& url, const String& protocol) 115 { 116 return adoptRef(new Bridge(workerClientWrapper, workerContext, taskMode, url, protocol)); 117 } 118 ~Bridge(); 119 void connect(); 120 bool send(const String& message); 121 unsigned long bufferedAmount(); 122 void close(); 123 void disconnect(); 124 void suspend(); 125 void resume(); 126 127 using RefCounted<Bridge>::ref; 128 using RefCounted<Bridge>::deref; 129 130 private: 131 Bridge(PassRefPtr<ThreadableWebSocketChannelClientWrapper>, PassRefPtr<WorkerContext>, const String& taskMode, const KURL&, const String& protocol); 132 133 static void setWebSocketChannel(ScriptExecutionContext*, Bridge* thisPtr, Peer*, RefPtr<ThreadableWebSocketChannelClientWrapper>); 134 135 // Executed on the main thread to create a Peer for this bridge. 136 static void mainThreadCreateWebSocketChannel(ScriptExecutionContext*, Bridge* thisPtr, RefPtr<ThreadableWebSocketChannelClientWrapper>, const String& taskMode, const KURL&, const String& protocol); 137 138 // Executed on the worker context's thread. 139 void clearClientWrapper(); 140 141 void setMethodNotCompleted(); 142 void waitForMethodCompletion(); 143 144 RefPtr<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; 145 RefPtr<WorkerContext> m_workerContext; 146 WorkerLoaderProxy& m_loaderProxy; 147 String m_taskMode; 148 Peer* m_peer; 149 }; 150 151 WorkerThreadableWebSocketChannel(WorkerContext*, WebSocketChannelClient*, const String& taskMode, const KURL&, const String& protocol); 152 153 static void mainThreadConnect(ScriptExecutionContext*, Peer*); 154 static void mainThreadSend(ScriptExecutionContext*, Peer*, const String& message); 155 static void mainThreadBufferedAmount(ScriptExecutionContext*, Peer*); 156 static void mainThreadClose(ScriptExecutionContext*, Peer*); 157 static void mainThreadDestroy(ScriptExecutionContext*, Peer*); 158 static void mainThreadSuspend(ScriptExecutionContext*, Peer*); 159 static void mainThreadResume(ScriptExecutionContext*, Peer*); 160 161 RefPtr<WorkerContext> m_workerContext; 162 RefPtr<ThreadableWebSocketChannelClientWrapper> m_workerClientWrapper; 163 RefPtr<Bridge> m_bridge; 164 }; 165 166 } // namespace WebCore 167 168 #endif // ENABLE(WEB_SOCKETS) 169 170 #endif // WorkerThreadableWebSocketChannel_h 171