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 WebSocket_h 32 #define WebSocket_h 33 34 #include "bindings/v8/ScriptWrappable.h" 35 #include "core/dom/ActiveDOMObject.h" 36 #include "core/events/EventListener.h" 37 #include "core/events/EventTarget.h" 38 #include "core/events/ThreadLocalEventNames.h" 39 #include "modules/websockets/WebSocketChannel.h" 40 #include "modules/websockets/WebSocketChannelClient.h" 41 #include "platform/Timer.h" 42 #include "platform/weborigin/KURL.h" 43 #include "wtf/Deque.h" 44 #include "wtf/Forward.h" 45 #include "wtf/OwnPtr.h" 46 #include "wtf/RefCounted.h" 47 #include "wtf/text/AtomicStringHash.h" 48 49 namespace WebCore { 50 51 class Blob; 52 class ExceptionState; 53 54 class WebSocket : public RefCounted<WebSocket>, public ScriptWrappable, public EventTargetWithInlineData, public ActiveDOMObject, public WebSocketChannelClient { 55 REFCOUNTED_EVENT_TARGET(WebSocket); 56 public: 57 static const char* subProtocolSeperator(); 58 // WebSocket instances must be used with a wrapper since this class's 59 // lifetime management is designed assuming the V8 holds a ref on it while 60 // hasPendingActivity() returns true. 61 static PassRefPtr<WebSocket> create(ExecutionContext*, const String& url, ExceptionState&); 62 static PassRefPtr<WebSocket> create(ExecutionContext*, const String& url, const String& protocol, ExceptionState&); 63 static PassRefPtr<WebSocket> create(ExecutionContext*, const String& url, const Vector<String>& protocols, ExceptionState&); 64 virtual ~WebSocket(); 65 66 enum State { 67 CONNECTING = 0, 68 OPEN = 1, 69 CLOSING = 2, 70 CLOSED = 3 71 }; 72 73 void connect(const String& url, ExceptionState&); 74 void connect(const String& url, const String& protocol, ExceptionState&); 75 void connect(const String& url, const Vector<String>& protocols, ExceptionState&); 76 77 void send(const String& message, ExceptionState&); 78 void send(ArrayBuffer*, ExceptionState&); 79 void send(ArrayBufferView*, ExceptionState&); 80 void send(Blob*, ExceptionState&); 81 82 // To distinguish close method call with the code parameter from one 83 // without, we have these three signatures. Use of 84 // Optional=DefaultIsUndefined in the IDL file doesn't help for now since 85 // it's bound to a value of 0 which is indistinguishable from the case 0 86 // is passed as code parameter. 87 void close(unsigned short code, const String& reason, ExceptionState&); 88 void close(ExceptionState&); 89 void close(unsigned short code, ExceptionState&); 90 91 const KURL& url() const; 92 State readyState() const; 93 unsigned long bufferedAmount() const; 94 95 String protocol() const; 96 String extensions() const; 97 98 String binaryType() const; 99 void setBinaryType(const String&); 100 101 DEFINE_ATTRIBUTE_EVENT_LISTENER(open); 102 DEFINE_ATTRIBUTE_EVENT_LISTENER(message); 103 DEFINE_ATTRIBUTE_EVENT_LISTENER(error); 104 DEFINE_ATTRIBUTE_EVENT_LISTENER(close); 105 106 // EventTarget functions. 107 virtual const AtomicString& interfaceName() const OVERRIDE; 108 virtual ExecutionContext* executionContext() const OVERRIDE; 109 110 // ActiveDOMObject functions. 111 virtual void contextDestroyed() OVERRIDE; 112 // Prevent this instance from being collected while it's not in CLOSED 113 // state. 114 virtual bool hasPendingActivity() const OVERRIDE; 115 virtual void suspend() OVERRIDE; 116 virtual void resume() OVERRIDE; 117 virtual void stop() OVERRIDE; 118 119 // WebSocketChannelClient functions. 120 virtual void didConnect() OVERRIDE; 121 virtual void didReceiveMessage(const String& message) OVERRIDE; 122 virtual void didReceiveBinaryData(PassOwnPtr<Vector<char> >) OVERRIDE; 123 virtual void didReceiveMessageError() OVERRIDE; 124 virtual void didUpdateBufferedAmount(unsigned long bufferedAmount) OVERRIDE; 125 virtual void didStartClosingHandshake() OVERRIDE; 126 virtual void didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus, unsigned short code, const String& reason) OVERRIDE; 127 128 private: 129 class EventQueue : public RefCounted<EventQueue> { 130 public: 131 static PassRefPtr<EventQueue> create(EventTarget* target) { return adoptRef(new EventQueue(target)); } 132 virtual ~EventQueue(); 133 134 // Dispatches the event if this queue is active. 135 // Queues the event if this queue is suspended. 136 // Does nothing otherwise. 137 void dispatch(PassRefPtr<Event> /* event */); 138 139 void suspend(); 140 void resume(); 141 void stop(); 142 143 private: 144 enum State { 145 Active, 146 Suspended, 147 Stopped, 148 }; 149 150 explicit EventQueue(EventTarget*); 151 152 // Dispatches queued events if this queue is active. 153 // Does nothing otherwise. 154 void dispatchQueuedEvents(); 155 void resumeTimerFired(Timer<EventQueue>*); 156 157 State m_state; 158 EventTarget* m_target; 159 Deque<RefPtr<Event> > m_events; 160 Timer<EventQueue> m_resumeTimer; 161 }; 162 163 explicit WebSocket(ExecutionContext*); 164 165 // Adds a console message with JSMessageSource and ErrorMessageLevel. 166 void logError(const String& message); 167 168 // Handle the JavaScript close method call. close() methods on this class 169 // are just for determining if the optional code argument is supplied or 170 // not. 171 void closeInternal(int, const String&, ExceptionState&); 172 173 size_t getFramingOverhead(size_t payloadSize); 174 175 // Checks the result of WebSocketChannel::send() method, and shows console 176 // message and sets ec appropriately. 177 void handleSendResult(WebSocketChannel::SendResult, ExceptionState&); 178 179 // Updates m_bufferedAmountAfterClose given the amount of data passed to 180 // send() method after the state changed to CLOSING or CLOSED. 181 void updateBufferedAmountAfterClose(unsigned long); 182 183 enum BinaryType { 184 BinaryTypeBlob, 185 BinaryTypeArrayBuffer 186 }; 187 188 RefPtr<WebSocketChannel> m_channel; 189 190 State m_state; 191 KURL m_url; 192 unsigned long m_bufferedAmount; 193 unsigned long m_bufferedAmountAfterClose; 194 BinaryType m_binaryType; 195 String m_subprotocol; 196 String m_extensions; 197 198 RefPtr<EventQueue> m_eventQueue; 199 }; 200 201 } // namespace WebCore 202 203 #endif // WebSocket_h 204