1 /* 2 * Copyright (C) 2013 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 NewWebSocketChannelImpl_h 32 #define NewWebSocketChannelImpl_h 33 34 #include "core/dom/ContextLifecycleObserver.h" 35 #include "core/fileapi/Blob.h" 36 #include "core/fileapi/FileError.h" 37 #include "core/frame/ConsoleTypes.h" 38 #include "modules/websockets/WebSocketChannel.h" 39 #include "platform/weborigin/KURL.h" 40 #include "public/platform/WebSocketHandle.h" 41 #include "public/platform/WebSocketHandleClient.h" 42 #include "wtf/ArrayBuffer.h" 43 #include "wtf/Deque.h" 44 #include "wtf/FastAllocBase.h" 45 #include "wtf/OwnPtr.h" 46 #include "wtf/PassOwnPtr.h" 47 #include "wtf/PassRefPtr.h" 48 #include "wtf/RefPtr.h" 49 #include "wtf/Vector.h" 50 #include "wtf/text/CString.h" 51 #include "wtf/text/WTFString.h" 52 53 namespace blink { 54 55 class Document; 56 class WebSocketHandshakeRequest; 57 class WebSocketHandshakeRequestInfo; 58 class WebSocketHandshakeResponseInfo; 59 60 // This class may replace MainThreadWebSocketChannel. 61 class NewWebSocketChannelImpl FINAL : public WebSocketChannel, public WebSocketHandleClient, public ContextLifecycleObserver { 62 public: 63 // You can specify the source file and the line number information 64 // explicitly by passing the last parameter. 65 // In the usual case, they are set automatically and you don't have to 66 // pass it. 67 // Specify handle explicitly only in tests. 68 static NewWebSocketChannelImpl* create(ExecutionContext* context, WebSocketChannelClient* client, const String& sourceURL = String(), unsigned lineNumber = 0, WebSocketHandle *handle = 0) 69 { 70 return adoptRefCountedGarbageCollected(new NewWebSocketChannelImpl(context, client, sourceURL, lineNumber, handle)); 71 } 72 virtual ~NewWebSocketChannelImpl(); 73 74 // WebSocketChannel functions. 75 virtual bool connect(const KURL&, const String& protocol) OVERRIDE; 76 virtual void send(const String& message) OVERRIDE; 77 virtual void send(const ArrayBuffer&, unsigned byteOffset, unsigned byteLength) OVERRIDE; 78 virtual void send(PassRefPtr<BlobDataHandle>) OVERRIDE; 79 virtual void send(PassOwnPtr<Vector<char> > data) OVERRIDE; 80 // Start closing handshake. Use the CloseEventCodeNotSpecified for the code 81 // argument to omit payload. 82 virtual void close(int code, const String& reason) OVERRIDE; 83 virtual void fail(const String& reason, MessageLevel, const String&, unsigned lineNumber) OVERRIDE; 84 virtual void disconnect() OVERRIDE; 85 86 virtual void suspend() OVERRIDE; 87 virtual void resume() OVERRIDE; 88 89 virtual void trace(Visitor*) OVERRIDE; 90 91 private: 92 enum MessageType { 93 MessageTypeText, 94 MessageTypeBlob, 95 MessageTypeArrayBuffer, 96 MessageTypeVector, 97 MessageTypeClose, 98 }; 99 100 struct Message { 101 explicit Message(const String&); 102 explicit Message(PassRefPtr<BlobDataHandle>); 103 explicit Message(PassRefPtr<ArrayBuffer>); 104 explicit Message(PassOwnPtr<Vector<char> >); 105 Message(unsigned short code, const String& reason); 106 107 MessageType type; 108 109 CString text; 110 RefPtr<BlobDataHandle> blobDataHandle; 111 RefPtr<ArrayBuffer> arrayBuffer; 112 OwnPtr<Vector<char> > vectorData; 113 unsigned short code; 114 String reason; 115 }; 116 117 struct ReceivedMessage { 118 bool isMessageText; 119 Vector<char> data; 120 }; 121 122 class BlobLoader; 123 124 NewWebSocketChannelImpl(ExecutionContext*, WebSocketChannelClient*, const String&, unsigned, WebSocketHandle*); 125 void sendInternal(); 126 void flowControlIfNecessary(); 127 void failAsError(const String& reason) { fail(reason, ErrorMessageLevel, m_sourceURLAtConstruction, m_lineNumberAtConstruction); } 128 void abortAsyncOperations(); 129 void handleDidClose(bool wasClean, unsigned short code, const String& reason); 130 Document* document(); // can be called only when m_identifier > 0. 131 132 // WebSocketHandleClient functions. 133 virtual void didConnect(WebSocketHandle*, bool fail, const WebString& selectedProtocol, const WebString& extensions) OVERRIDE; 134 virtual void didStartOpeningHandshake(WebSocketHandle*, const WebSocketHandshakeRequestInfo&) OVERRIDE; 135 virtual void didFinishOpeningHandshake(WebSocketHandle*, const WebSocketHandshakeResponseInfo&) OVERRIDE; 136 virtual void didFail(WebSocketHandle*, const WebString& message) OVERRIDE; 137 virtual void didReceiveData(WebSocketHandle*, bool fin, WebSocketHandle::MessageType, const char* data, size_t /* size */) OVERRIDE; 138 virtual void didClose(WebSocketHandle*, bool wasClean, unsigned short code, const WebString& reason) OVERRIDE; 139 virtual void didReceiveFlowControl(WebSocketHandle*, int64_t quota) OVERRIDE; 140 virtual void didStartClosingHandshake(WebSocketHandle*) OVERRIDE; 141 142 // Methods for BlobLoader. 143 void didFinishLoadingBlob(PassRefPtr<ArrayBuffer>); 144 void didFailLoadingBlob(FileError::ErrorCode); 145 146 // LifecycleObserver functions. 147 virtual void contextDestroyed() OVERRIDE 148 { 149 // In oilpan we cannot assume this channel's finalizer has been called 150 // before the document it is observing is dead and finalized since there 151 // is no eager finalization. Instead the finalization happens at the 152 // next GC which could be long enough after the Peer::destroy call for 153 // the context (ie. Document) to be dead too. If the context's finalizer 154 // is run first this method gets called. Instead we assert the channel 155 // has been disconnected which happens in Peer::destroy. 156 ASSERT(!m_handle); 157 ASSERT(!m_client); 158 ASSERT(!m_identifier); 159 ContextLifecycleObserver::contextDestroyed(); 160 } 161 162 // m_handle is a handle of the connection. 163 // m_handle == 0 means this channel is closed. 164 OwnPtr<WebSocketHandle> m_handle; 165 166 // m_client can be deleted while this channel is alive, but this class 167 // expects that disconnect() is called before the deletion. 168 Member<WebSocketChannelClient> m_client; 169 KURL m_url; 170 // m_identifier > 0 means calling scriptContextExecution() returns a Document. 171 unsigned long m_identifier; 172 Member<BlobLoader> m_blobLoader; 173 Deque<OwnPtr<Message> > m_messages; 174 Vector<char> m_receivingMessageData; 175 176 bool m_receivingMessageTypeIsText; 177 int64_t m_sendingQuota; 178 int64_t m_receivedDataSizeForFlowControl; 179 size_t m_sentSizeOfTopMessage; 180 181 String m_sourceURLAtConstruction; 182 unsigned m_lineNumberAtConstruction; 183 RefPtr<WebSocketHandshakeRequest> m_handshakeRequest; 184 185 static const int64_t receivedDataSizeForFlowControlHighWaterMark = 1 << 15; 186 }; 187 188 } // namespace blink 189 190 #endif // NewWebSocketChannelImpl_h 191