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 DOMWebSocket_h 32 #define DOMWebSocket_h 33 34 #include "core/dom/ActiveDOMObject.h" 35 #include "core/events/EventListener.h" 36 #include "modules/EventTargetModules.h" 37 #include "modules/websockets/WebSocketChannel.h" 38 #include "modules/websockets/WebSocketChannelClient.h" 39 #include "platform/Timer.h" 40 #include "platform/heap/Handle.h" 41 #include "platform/weborigin/KURL.h" 42 #include "wtf/Deque.h" 43 #include "wtf/Forward.h" 44 #include "wtf/text/AtomicStringHash.h" 45 46 namespace blink { 47 48 class Blob; 49 class ExceptionState; 50 51 class DOMWebSocket : public RefCountedGarbageCollectedWillBeGarbageCollectedFinalized<DOMWebSocket>, public EventTargetWithInlineData, public ActiveDOMObject, public WebSocketChannelClient { 52 DEFINE_EVENT_TARGET_REFCOUNTING_WILL_BE_REMOVED(RefCountedGarbageCollected<DOMWebSocket>); 53 DEFINE_WRAPPERTYPEINFO(); 54 USING_GARBAGE_COLLECTED_MIXIN(DOMWebSocket); 55 public: 56 static const char* subprotocolSeperator(); 57 // DOMWebSocket instances must be used with a wrapper since this class's 58 // lifetime management is designed assuming the V8 holds a ref on it while 59 // hasPendingActivity() returns true. 60 static DOMWebSocket* create(ExecutionContext*, const String& url, ExceptionState&); 61 static DOMWebSocket* create(ExecutionContext*, const String& url, const String& protocol, ExceptionState&); 62 static DOMWebSocket* create(ExecutionContext*, const String& url, const Vector<String>& protocols, ExceptionState&); 63 virtual ~DOMWebSocket(); 64 65 enum State { 66 CONNECTING = 0, 67 OPEN = 1, 68 CLOSING = 2, 69 CLOSED = 3 70 }; 71 72 void connect(const String& url, const Vector<String>& protocols, ExceptionState&); 73 74 void send(const String& message, ExceptionState&); 75 void send(ArrayBuffer*, ExceptionState&); 76 void send(ArrayBufferView*, ExceptionState&); 77 void send(Blob*, ExceptionState&); 78 79 // To distinguish close method call with the code parameter from one 80 // without, we have these three signatures. Use of 81 // Optional=DefaultIsUndefined in the IDL file doesn't help for now since 82 // it's bound to a value of 0 which is indistinguishable from the case 0 83 // is passed as code parameter. 84 void close(unsigned short code, const String& reason, ExceptionState&); 85 void close(ExceptionState&); 86 void close(unsigned short code, ExceptionState&); 87 88 const KURL& url() const; 89 State readyState() const; 90 unsigned long bufferedAmount() const; 91 92 String protocol() const; 93 String extensions() const; 94 95 String binaryType() const; 96 void setBinaryType(const String&); 97 98 DEFINE_ATTRIBUTE_EVENT_LISTENER(open); 99 DEFINE_ATTRIBUTE_EVENT_LISTENER(message); 100 DEFINE_ATTRIBUTE_EVENT_LISTENER(error); 101 DEFINE_ATTRIBUTE_EVENT_LISTENER(close); 102 103 // EventTarget functions. 104 virtual const AtomicString& interfaceName() const OVERRIDE; 105 virtual ExecutionContext* executionContext() const OVERRIDE; 106 107 // ActiveDOMObject functions. 108 virtual void contextDestroyed() OVERRIDE; 109 // Prevent this instance from being collected while it's not in CLOSED 110 // state. 111 virtual bool hasPendingActivity() const OVERRIDE; 112 virtual void suspend() OVERRIDE; 113 virtual void resume() OVERRIDE; 114 virtual void stop() OVERRIDE; 115 116 // WebSocketChannelClient functions. 117 virtual void didConnect(const String& subprotocol, const String& extensions) OVERRIDE; 118 virtual void didReceiveMessage(const String& message) OVERRIDE; 119 virtual void didReceiveBinaryData(PassOwnPtr<Vector<char> >) OVERRIDE; 120 virtual void didReceiveMessageError() OVERRIDE; 121 virtual void didConsumeBufferedAmount(unsigned long) OVERRIDE; 122 virtual void didStartClosingHandshake() OVERRIDE; 123 virtual void didClose(ClosingHandshakeCompletionStatus, unsigned short code, const String& reason) OVERRIDE; 124 125 virtual void trace(Visitor*) OVERRIDE; 126 127 static bool isValidSubprotocolString(const String&); 128 129 protected: 130 explicit DOMWebSocket(ExecutionContext*); 131 132 private: 133 // FIXME: This should inherit blink::EventQueue. 134 class EventQueue FINAL : public GarbageCollectedFinalized<EventQueue> { 135 public: 136 static EventQueue* create(EventTarget* target) 137 { 138 return new EventQueue(target); 139 } 140 ~EventQueue(); 141 142 // Dispatches the event if this queue is active. 143 // Queues the event if this queue is suspended. 144 // Does nothing otherwise. 145 void dispatch(PassRefPtrWillBeRawPtr<Event> /* event */); 146 147 bool isEmpty() const; 148 149 void suspend(); 150 void resume(); 151 void stop(); 152 153 void trace(Visitor*); 154 155 private: 156 enum State { 157 Active, 158 Suspended, 159 Stopped, 160 }; 161 162 explicit EventQueue(EventTarget*); 163 164 // Dispatches queued events if this queue is active. 165 // Does nothing otherwise. 166 void dispatchQueuedEvents(); 167 void resumeTimerFired(Timer<EventQueue>*); 168 169 State m_state; 170 EventTarget* m_target; 171 WillBeHeapDeque<RefPtrWillBeMember<Event> > m_events; 172 Timer<EventQueue> m_resumeTimer; 173 }; 174 175 enum WebSocketSendType { 176 WebSocketSendTypeString, 177 WebSocketSendTypeArrayBuffer, 178 WebSocketSendTypeArrayBufferView, 179 WebSocketSendTypeBlob, 180 WebSocketSendTypeMax, 181 }; 182 183 // This function is virtual for unittests. 184 // FIXME: Move WebSocketChannel::create here. 185 virtual WebSocketChannel* createChannel(ExecutionContext* context, WebSocketChannelClient* client) 186 { 187 return WebSocketChannel::create(context, client); 188 } 189 190 // Adds a console message with JSMessageSource and ErrorMessageLevel. 191 void logError(const String& message); 192 193 // Handle the JavaScript close method call. close() methods on this class 194 // are just for determining if the optional code argument is supplied or 195 // not. 196 void closeInternal(int, const String&, ExceptionState&); 197 198 size_t getFramingOverhead(size_t payloadSize); 199 200 // Updates m_bufferedAmountAfterClose given the amount of data passed to 201 // send() method after the state changed to CLOSING or CLOSED. 202 void updateBufferedAmountAfterClose(unsigned long); 203 void reflectBufferedAmountConsumption(Timer<DOMWebSocket>*); 204 205 void releaseChannel(); 206 207 enum BinaryType { 208 BinaryTypeBlob, 209 BinaryTypeArrayBuffer 210 }; 211 212 Member<WebSocketChannel> m_channel; 213 214 State m_state; 215 KURL m_url; 216 unsigned long m_bufferedAmount; 217 // The consumed buffered amount that will be reflected to m_bufferedAmount 218 // later. It will be cleared once reflected. 219 unsigned long m_consumedBufferedAmount; 220 unsigned long m_bufferedAmountAfterClose; 221 BinaryType m_binaryType; 222 // The subprotocol the server selected. 223 String m_subprotocol; 224 String m_extensions; 225 226 Member<EventQueue> m_eventQueue; 227 Timer<DOMWebSocket> m_bufferedAmountConsumeTimer; 228 }; 229 230 } // namespace blink 231 232 #endif // DOMWebSocket_h 233